mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
[3.13] gh-82951: Fix serializing by name in pickle protocols < 4 (GH-122149) (GH-122264)
Serializing objects with complex __qualname__ (such as unbound methods and
nested classes) by name no longer involves serializing parent objects by value
in pickle protocols < 4.
(cherry picked from commit dc07f65a53
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
977c799286
commit
984f8aaa2f
4 changed files with 82 additions and 26 deletions
|
@ -3592,7 +3592,6 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
PyObject *module = NULL;
|
||||
PyObject *parent = NULL;
|
||||
PyObject *dotted_path = NULL;
|
||||
PyObject *lastname = NULL;
|
||||
PyObject *cls;
|
||||
int status = 0;
|
||||
|
||||
|
@ -3633,10 +3632,7 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
obj, module_name);
|
||||
goto error;
|
||||
}
|
||||
lastname = Py_NewRef(PyList_GET_ITEM(dotted_path,
|
||||
PyList_GET_SIZE(dotted_path) - 1));
|
||||
cls = get_deep_attribute(module, dotted_path, &parent);
|
||||
Py_CLEAR(dotted_path);
|
||||
if (cls == NULL) {
|
||||
PyErr_Format(st->PicklingError,
|
||||
"Can't pickle %R: attribute lookup %S on %S failed",
|
||||
|
@ -3724,7 +3720,10 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
else {
|
||||
gen_global:
|
||||
if (parent == module) {
|
||||
Py_SETREF(global_name, Py_NewRef(lastname));
|
||||
Py_SETREF(global_name,
|
||||
Py_NewRef(PyList_GET_ITEM(dotted_path,
|
||||
PyList_GET_SIZE(dotted_path) - 1)));
|
||||
Py_CLEAR(dotted_path);
|
||||
}
|
||||
if (self->proto >= 4) {
|
||||
const char stack_global_op = STACK_GLOBAL;
|
||||
|
@ -3737,20 +3736,30 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
if (_Pickler_Write(self, &stack_global_op, 1) < 0)
|
||||
goto error;
|
||||
}
|
||||
else if (parent != module) {
|
||||
PyObject *reduce_value = Py_BuildValue("(O(OO))",
|
||||
st->getattr, parent, lastname);
|
||||
if (reduce_value == NULL)
|
||||
goto error;
|
||||
status = save_reduce(st, self, reduce_value, NULL);
|
||||
Py_DECREF(reduce_value);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
}
|
||||
else {
|
||||
/* Generate a normal global opcode if we are using a pickle
|
||||
protocol < 4, or if the object is not registered in the
|
||||
extension registry. */
|
||||
extension registry.
|
||||
|
||||
Objects with multi-part __qualname__ are represented as
|
||||
getattr(getattr(..., attrname1), attrname2). */
|
||||
const char mark_op = MARK;
|
||||
const char tupletwo_op = (self->proto < 2) ? TUPLE : TUPLE2;
|
||||
const char reduce_op = REDUCE;
|
||||
Py_ssize_t i;
|
||||
if (dotted_path) {
|
||||
if (PyList_GET_SIZE(dotted_path) > 1) {
|
||||
Py_SETREF(global_name, Py_NewRef(PyList_GET_ITEM(dotted_path, 0)));
|
||||
}
|
||||
for (i = 1; i < PyList_GET_SIZE(dotted_path); i++) {
|
||||
if (save(st, self, st->getattr, 0) < 0 ||
|
||||
(self->proto < 2 && _Pickler_Write(self, &mark_op, 1) < 0))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *encoded;
|
||||
PyObject *(*unicode_encoder)(PyObject *);
|
||||
|
||||
|
@ -3812,6 +3821,17 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
Py_DECREF(encoded);
|
||||
if (_Pickler_Write(self, "\n", 1) < 0)
|
||||
goto error;
|
||||
|
||||
if (dotted_path) {
|
||||
for (i = 1; i < PyList_GET_SIZE(dotted_path); i++) {
|
||||
if (save(st, self, PyList_GET_ITEM(dotted_path, i), 0) < 0 ||
|
||||
_Pickler_Write(self, &tupletwo_op, 1) < 0 ||
|
||||
_Pickler_Write(self, &reduce_op, 1) < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Memoize the object. */
|
||||
if (memo_put(st, self, obj) < 0)
|
||||
|
@ -3827,7 +3847,6 @@ save_global(PickleState *st, PicklerObject *self, PyObject *obj,
|
|||
Py_XDECREF(module);
|
||||
Py_XDECREF(parent);
|
||||
Py_XDECREF(dotted_path);
|
||||
Py_XDECREF(lastname);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue