mirror of
https://github.com/python/cpython.git
synced 2026-05-06 12:49:07 -04:00
gh-146563: add exception note for invalid Expat handler return values (#146565)
This commit is contained in:
@@ -29,7 +29,8 @@ PyAPI_FUNC(PyObject*) _PyErr_FormatFromCause(
|
||||
...
|
||||
);
|
||||
|
||||
extern int _PyException_AddNote(
|
||||
// Export for 'pyexpat' shared extension.
|
||||
PyAPI_FUNC(int) _PyException_AddNote(
|
||||
PyObject *exc,
|
||||
PyObject *note);
|
||||
|
||||
|
||||
@@ -510,6 +510,34 @@ class HandlerExceptionTest(unittest.TestCase):
|
||||
self.assertIn('call_with_frame("StartElement"',
|
||||
entries[1].line)
|
||||
|
||||
def test_invalid_NotStandalone(self):
|
||||
parser = expat.ParserCreate()
|
||||
parser.NotStandaloneHandler = mock.Mock(return_value="bad value")
|
||||
parser.ElementDeclHandler = lambda _1, _2: None
|
||||
|
||||
payload = b"""\
|
||||
<!DOCTYPE quotations SYSTEM "quotations.dtd" [<!ELEMENT root ANY>]><root/>
|
||||
"""
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
parser.Parse(payload, True)
|
||||
parser.NotStandaloneHandler.assert_called_once()
|
||||
|
||||
notes = ["invalid 'NotStandalone' event handler return value"]
|
||||
self.assertEqual(cm.exception.__notes__, notes)
|
||||
|
||||
def test_invalid_ExternalEntityRefHandler(self):
|
||||
parser = expat.ParserCreate()
|
||||
parser.UseForeignDTD()
|
||||
parser.SetParamEntityParsing(expat.XML_PARAM_ENTITY_PARSING_ALWAYS)
|
||||
parser.ExternalEntityRefHandler = mock.Mock(return_value=None)
|
||||
|
||||
with self.assertRaises(TypeError) as cm:
|
||||
parser.Parse(b"<?xml version='1.0'?><element/>", True)
|
||||
parser.ExternalEntityRefHandler.assert_called_once()
|
||||
|
||||
notes = ["invalid 'ExternalEntityRef' event handler return value"]
|
||||
self.assertEqual(cm.exception.__notes__, notes)
|
||||
|
||||
|
||||
# Test Current* members:
|
||||
class PositionTest(unittest.TestCase):
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
:mod:`xml.parsers.expat`: add an exception note when a custom Expat handler
|
||||
return value cannot be properly interpreted. Patch by Bénédikt Tran.
|
||||
@@ -503,6 +503,28 @@ my_StartElementHandler(void *userData,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
invalid_expat_handler_rv(const char *name)
|
||||
{
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
assert(exc != NULL);
|
||||
PyObject *note = PyUnicode_FromFormat("invalid '%s' event handler return value", name);
|
||||
if (note == NULL) {
|
||||
goto error;
|
||||
}
|
||||
int rc = _PyException_AddNote(exc, note);
|
||||
Py_DECREF(note);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
};
|
||||
goto done;
|
||||
|
||||
error:
|
||||
PyErr_Clear();
|
||||
done:
|
||||
PyErr_SetRaisedException(exc);
|
||||
}
|
||||
|
||||
#define RC_HANDLER(RETURN_TYPE, NAME, PARAMS, \
|
||||
INIT, PARSE_FORMAT, CONVERSION, \
|
||||
RETURN_VARIABLE, GETUSERDATA) \
|
||||
@@ -536,6 +558,9 @@ my_ ## NAME ## Handler PARAMS { \
|
||||
} \
|
||||
CONVERSION \
|
||||
Py_DECREF(rv); \
|
||||
if (PyErr_Occurred()) { \
|
||||
invalid_expat_handler_rv(#NAME); \
|
||||
} \
|
||||
return RETURN_VARIABLE; \
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user