@@ -413,21 +413,33 @@ write_escaped_unicode(PyUnicodeWriter *writer, PyObject *pystr)
413413static void
414414raise_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
433445static void
0 commit comments