Skip to content

Commit 9477824

Browse files
gh-143544: Fix use-after-free in _json.raise_errmsg
1 parent c07e5ec commit 9477824

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

Modules/_json.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -413,21 +413,33 @@ write_escaped_unicode(PyUnicodeWriter *writer, PyObject *pystr)
413413
static void
414414
raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end)
415415
{
416-
/* Use JSONDecodeError exception to raise a nice looking ValueError subclass */
417416
_Py_DECLARE_STR(json_decoder, "json.decoder");
418-
PyObject *JSONDecodeError =
419-
PyImport_ImportModuleAttr(&_Py_STR(json_decoder), &_Py_ID(JSONDecodeError));
420-
if (JSONDecodeError == NULL) {
417+
418+
PyObject *json_error =
419+
PyImport_ImportModuleAttr(&_Py_STR(json_decoder), &_Py_ID(JSONDecodeError));
420+
if (json_error == NULL) {
421421
return;
422422
}
423423

424-
PyObject *exc;
425-
exc = PyObject_CallFunction(JSONDecodeError, "zOn", msg, s, end);
426-
Py_DECREF(JSONDecodeError);
427-
if (exc) {
428-
PyErr_SetObject(JSONDecodeError, exc);
424+
/* Hold a strong reference across user code execution */
425+
PyObject *error_type = Py_NewRef(json_error);
426+
427+
PyObject *exc = PyObject_CallFunction(error_type, "zOn", msg, s, end);
428+
429+
if (exc != NULL) {
430+
/* Only use it if it's a valid exception type */
431+
if (PyExceptionClass_Check(error_type)) {
432+
PyErr_SetObject(error_type, exc);
433+
}
434+
else {
435+
/* Fallback: always safe */
436+
PyErr_SetString(PyExc_ValueError, msg);
437+
}
429438
Py_DECREF(exc);
430439
}
440+
441+
Py_DECREF(error_type);
442+
Py_DECREF(json_error);
431443
}
432444

433445
static void

0 commit comments

Comments
 (0)