Skip to content

Commit d0058cb

Browse files
aiskcolesbury
andauthored
gh-111928: make "memo" dict local to scan_once call (gh-112005)
Co-authored-by: Sam Gross <[email protected]>
1 parent 9a2f25d commit d0058cb

File tree

1 file changed

+19
-23
lines changed

1 file changed

+19
-23
lines changed

Modules/_json.c

+19-23
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ typedef struct _PyScannerObject {
2424
PyObject *parse_float;
2525
PyObject *parse_int;
2626
PyObject *parse_constant;
27-
PyObject *memo;
2827
} PyScannerObject;
2928

3029
static PyMemberDef scanner_members[] = {
@@ -70,7 +69,7 @@ ascii_escape_unicode(PyObject *pystr);
7069
static PyObject *
7170
py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
7271
static PyObject *
73-
scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
72+
scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
7473
static PyObject *
7574
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
7675
static PyObject *
@@ -631,7 +630,6 @@ scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
631630
Py_VISIT(self->parse_float);
632631
Py_VISIT(self->parse_int);
633632
Py_VISIT(self->parse_constant);
634-
Py_VISIT(self->memo);
635633
return 0;
636634
}
637635

@@ -643,12 +641,11 @@ scanner_clear(PyScannerObject *self)
643641
Py_CLEAR(self->parse_float);
644642
Py_CLEAR(self->parse_int);
645643
Py_CLEAR(self->parse_constant);
646-
Py_CLEAR(self->memo);
647644
return 0;
648645
}
649646

650647
static PyObject *
651-
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
648+
_parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
652649
{
653650
/* Read a JSON object from PyUnicode pystr.
654651
idx is the index of the first character after the opening curly brace.
@@ -693,7 +690,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
693690
key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
694691
if (key == NULL)
695692
goto bail;
696-
memokey = PyDict_SetDefault(s->memo, key, key);
693+
memokey = PyDict_SetDefault(memo, key, key);
697694
if (memokey == NULL) {
698695
goto bail;
699696
}
@@ -710,7 +707,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
710707
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
711708

712709
/* read any JSON term */
713-
val = scan_once_unicode(s, pystr, idx, &next_idx);
710+
val = scan_once_unicode(s, memo, pystr, idx, &next_idx);
714711
if (val == NULL)
715712
goto bail;
716713

@@ -774,7 +771,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
774771
}
775772

776773
static PyObject *
777-
_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
774+
_parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
778775
/* Read a JSON array from PyUnicode pystr.
779776
idx is the index of the first character after the opening brace.
780777
*next_idx_ptr is a return-by-reference index to the first character after
@@ -805,7 +802,7 @@ _parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssi
805802
while (1) {
806803

807804
/* read any JSON term */
808-
val = scan_once_unicode(s, pystr, idx, &next_idx);
805+
val = scan_once_unicode(s, memo, pystr, idx, &next_idx);
809806
if (val == NULL)
810807
goto bail;
811808

@@ -986,7 +983,7 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
986983
}
987984

988985
static PyObject *
989-
scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
986+
scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
990987
{
991988
/* Read one JSON term (of any kind) from PyUnicode pystr.
992989
idx is the index of the first character of the term
@@ -1022,15 +1019,15 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
10221019
if (_Py_EnterRecursiveCall(" while decoding a JSON object "
10231020
"from a unicode string"))
10241021
return NULL;
1025-
res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr);
1022+
res = _parse_object_unicode(s, memo, pystr, idx + 1, next_idx_ptr);
10261023
_Py_LeaveRecursiveCall();
10271024
return res;
10281025
case '[':
10291026
/* array */
10301027
if (_Py_EnterRecursiveCall(" while decoding a JSON array "
10311028
"from a unicode string"))
10321029
return NULL;
1033-
res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr);
1030+
res = _parse_array_unicode(s, memo, pystr, idx + 1, next_idx_ptr);
10341031
_Py_LeaveRecursiveCall();
10351032
return res;
10361033
case 'n':
@@ -1106,16 +1103,19 @@ scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
11061103
if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:scan_once", kwlist, &pystr, &idx))
11071104
return NULL;
11081105

1109-
if (PyUnicode_Check(pystr)) {
1110-
rval = scan_once_unicode(self, pystr, idx, &next_idx);
1111-
}
1112-
else {
1106+
if (!PyUnicode_Check(pystr)) {
11131107
PyErr_Format(PyExc_TypeError,
1114-
"first argument must be a string, not %.80s",
1115-
Py_TYPE(pystr)->tp_name);
1108+
"first argument must be a string, not %.80s",
1109+
Py_TYPE(pystr)->tp_name);
11161110
return NULL;
11171111
}
1118-
PyDict_Clear(self->memo);
1112+
1113+
PyObject *memo = PyDict_New();
1114+
if (memo == NULL) {
1115+
return NULL;
1116+
}
1117+
rval = scan_once_unicode(self, memo, pystr, idx, &next_idx);
1118+
Py_DECREF(memo);
11191119
if (rval == NULL)
11201120
return NULL;
11211121
return _build_rval_index_tuple(rval, next_idx);
@@ -1137,10 +1137,6 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11371137
return NULL;
11381138
}
11391139

1140-
s->memo = PyDict_New();
1141-
if (s->memo == NULL)
1142-
goto bail;
1143-
11441140
/* All of these will fail "gracefully" so we don't need to verify them */
11451141
strict = PyObject_GetAttrString(ctx, "strict");
11461142
if (strict == NULL)

0 commit comments

Comments
 (0)