gh-123431: Harmonize extension code checks in pickle (GH-123434)

This checks are redundant in normal circumstances and can only work if
the extension registry was intentionally broken.

* The Python implementation now raises exception for the extension code
  with false boolean value.
* Simplify the C code. RuntimeError is now raised in explicit checks.
* Add many tests.
This commit is contained in:
Serhiy Storchaka 2024-08-29 08:26:16 +03:00 committed by GitHub
parent c9930f5022
commit 0c3ea30238
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 73 additions and 28 deletions

View file

@ -3650,34 +3650,24 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
if (extension_key == NULL) {
goto error;
}
code_obj = PyDict_GetItemWithError(st->extension_registry,
extension_key);
if (PyDict_GetItemRef(st->extension_registry, extension_key, &code_obj) < 0) {
Py_DECREF(extension_key);
goto error;
}
Py_DECREF(extension_key);
/* The object is not registered in the extension registry.
This is the most likely code path. */
if (code_obj == NULL) {
if (PyErr_Occurred()) {
goto error;
}
/* The object is not registered in the extension registry.
This is the most likely code path. */
goto gen_global;
}
/* XXX: pickle.py doesn't check neither the type, nor the range
of the value returned by the extension_registry. It should for
consistency. */
/* Verify code_obj has the right type and value. */
if (!PyLong_Check(code_obj)) {
PyErr_Format(st->PicklingError,
"Can't pickle %R: extension code %R isn't an integer",
obj, code_obj);
goto error;
}
code = PyLong_AS_LONG(code_obj);
code = PyLong_AsLong(code_obj);
Py_DECREF(code_obj);
if (code <= 0 || code > 0x7fffffffL) {
/* Should never happen in normal circumstances, since the type and
the value of the code are checked in copyreg.add_extension(). */
if (!PyErr_Occurred())
PyErr_Format(st->PicklingError, "Can't pickle %R: extension "
"code %ld is out of range", obj, code);
PyErr_Format(PyExc_RuntimeError, "extension code %ld is out of range", code);
goto error;
}