gh-111928: make "memo" dict local to scan_once call (gh-112005)

Co-authored-by: Sam Gross <colesbury@gmail.com>
This commit is contained in:
AN Long 2023-11-13 12:58:34 +08:00 committed by GitHub
parent 9a2f25d374
commit d0058cbd1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -24,7 +24,6 @@ typedef struct _PyScannerObject {
PyObject *parse_float; PyObject *parse_float;
PyObject *parse_int; PyObject *parse_int;
PyObject *parse_constant; PyObject *parse_constant;
PyObject *memo;
} PyScannerObject; } PyScannerObject;
static PyMemberDef scanner_members[] = { static PyMemberDef scanner_members[] = {
@ -70,7 +69,7 @@ ascii_escape_unicode(PyObject *pystr);
static PyObject * static PyObject *
py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr); py_encode_basestring_ascii(PyObject* Py_UNUSED(self), PyObject *pystr);
static PyObject * static PyObject *
scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr); scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr);
static PyObject * static PyObject *
_build_rval_index_tuple(PyObject *rval, Py_ssize_t idx); _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx);
static PyObject * static PyObject *
@ -631,7 +630,6 @@ scanner_traverse(PyScannerObject *self, visitproc visit, void *arg)
Py_VISIT(self->parse_float); Py_VISIT(self->parse_float);
Py_VISIT(self->parse_int); Py_VISIT(self->parse_int);
Py_VISIT(self->parse_constant); Py_VISIT(self->parse_constant);
Py_VISIT(self->memo);
return 0; return 0;
} }
@ -643,12 +641,11 @@ scanner_clear(PyScannerObject *self)
Py_CLEAR(self->parse_float); Py_CLEAR(self->parse_float);
Py_CLEAR(self->parse_int); Py_CLEAR(self->parse_int);
Py_CLEAR(self->parse_constant); Py_CLEAR(self->parse_constant);
Py_CLEAR(self->memo);
return 0; return 0;
} }
static PyObject * static PyObject *
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
{ {
/* Read a JSON object from PyUnicode pystr. /* Read a JSON object from PyUnicode pystr.
idx is the index of the first character after the opening curly brace. 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
key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx); key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
if (key == NULL) if (key == NULL)
goto bail; goto bail;
memokey = PyDict_SetDefault(s->memo, key, key); memokey = PyDict_SetDefault(memo, key, key);
if (memokey == NULL) { if (memokey == NULL) {
goto bail; goto bail;
} }
@ -710,7 +707,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++;
/* read any JSON term */ /* read any JSON term */
val = scan_once_unicode(s, pystr, idx, &next_idx); val = scan_once_unicode(s, memo, pystr, idx, &next_idx);
if (val == NULL) if (val == NULL)
goto bail; goto bail;
@ -774,7 +771,7 @@ bail:
} }
static PyObject * static PyObject *
_parse_array_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) { _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
/* Read a JSON array from PyUnicode pystr. /* Read a JSON array from PyUnicode pystr.
idx is the index of the first character after the opening brace. idx is the index of the first character after the opening brace.
*next_idx_ptr is a return-by-reference index to the first character after *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
while (1) { while (1) {
/* read any JSON term */ /* read any JSON term */
val = scan_once_unicode(s, pystr, idx, &next_idx); val = scan_once_unicode(s, memo, pystr, idx, &next_idx);
if (val == NULL) if (val == NULL)
goto bail; goto bail;
@ -986,7 +983,7 @@ _match_number_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t start, Py_
} }
static PyObject * static PyObject *
scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) scan_once_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
{ {
/* Read one JSON term (of any kind) from PyUnicode pystr. /* Read one JSON term (of any kind) from PyUnicode pystr.
idx is the index of the first character of the term idx is the index of the first character of the term
@ -1022,7 +1019,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
if (_Py_EnterRecursiveCall(" while decoding a JSON object " if (_Py_EnterRecursiveCall(" while decoding a JSON object "
"from a unicode string")) "from a unicode string"))
return NULL; return NULL;
res = _parse_object_unicode(s, pystr, idx + 1, next_idx_ptr); res = _parse_object_unicode(s, memo, pystr, idx + 1, next_idx_ptr);
_Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return res; return res;
case '[': case '[':
@ -1030,7 +1027,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
if (_Py_EnterRecursiveCall(" while decoding a JSON array " if (_Py_EnterRecursiveCall(" while decoding a JSON array "
"from a unicode string")) "from a unicode string"))
return NULL; return NULL;
res = _parse_array_unicode(s, pystr, idx + 1, next_idx_ptr); res = _parse_array_unicode(s, memo, pystr, idx + 1, next_idx_ptr);
_Py_LeaveRecursiveCall(); _Py_LeaveRecursiveCall();
return res; return res;
case 'n': case 'n':
@ -1106,16 +1103,19 @@ scanner_call(PyScannerObject *self, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:scan_once", kwlist, &pystr, &idx)) if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:scan_once", kwlist, &pystr, &idx))
return NULL; return NULL;
if (PyUnicode_Check(pystr)) { if (!PyUnicode_Check(pystr)) {
rval = scan_once_unicode(self, pystr, idx, &next_idx);
}
else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"first argument must be a string, not %.80s", "first argument must be a string, not %.80s",
Py_TYPE(pystr)->tp_name); Py_TYPE(pystr)->tp_name);
return NULL; return NULL;
} }
PyDict_Clear(self->memo);
PyObject *memo = PyDict_New();
if (memo == NULL) {
return NULL;
}
rval = scan_once_unicode(self, memo, pystr, idx, &next_idx);
Py_DECREF(memo);
if (rval == NULL) if (rval == NULL)
return NULL; return NULL;
return _build_rval_index_tuple(rval, next_idx); return _build_rval_index_tuple(rval, next_idx);
@ -1137,10 +1137,6 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL; return NULL;
} }
s->memo = PyDict_New();
if (s->memo == NULL)
goto bail;
/* All of these will fail "gracefully" so we don't need to verify them */ /* All of these will fail "gracefully" so we don't need to verify them */
strict = PyObject_GetAttrString(ctx, "strict"); strict = PyObject_GetAttrString(ctx, "strict");
if (strict == NULL) if (strict == NULL)