mirror of
https://github.com/python/cpython.git
synced 2026-05-08 03:21:16 +00:00
[3.14] gh-148653: Fix some marshal errors related to recursive immutable objects (GH-148698) (GH-148711)
Forbid marshalling recursive code and slice objects which
cannot be correctly unmarshalled.
Add multiple tests for recursive data structures.
(cherry picked from commit 2e37d83641)
This commit is contained in:
parent
67100b3e92
commit
d496c637a3
3 changed files with 156 additions and 7 deletions
|
|
@ -380,7 +380,6 @@ static int
|
|||
w_ref(PyObject *v, char *flag, WFILE *p)
|
||||
{
|
||||
_Py_hashtable_entry_t *entry;
|
||||
int w;
|
||||
|
||||
if (p->version < 3 || p->hashtable == NULL)
|
||||
return 0; /* not writing object references */
|
||||
|
|
@ -397,20 +396,28 @@ w_ref(PyObject *v, char *flag, WFILE *p)
|
|||
entry = _Py_hashtable_get_entry(p->hashtable, v);
|
||||
if (entry != NULL) {
|
||||
/* write the reference index to the stream */
|
||||
w = (int)(uintptr_t)entry->value;
|
||||
uintptr_t w = (uintptr_t)entry->value;
|
||||
if (w & 0x80000000LU) {
|
||||
PyErr_Format(PyExc_ValueError, "cannot marshal recursion %T objects", v);
|
||||
goto err;
|
||||
}
|
||||
/* we don't store "long" indices in the dict */
|
||||
assert(0 <= w && w <= 0x7fffffff);
|
||||
assert(w <= 0x7fffffff);
|
||||
w_byte(TYPE_REF, p);
|
||||
w_long(w, p);
|
||||
w_long((int)w, p);
|
||||
return 1;
|
||||
} else {
|
||||
size_t s = p->hashtable->nentries;
|
||||
size_t w = p->hashtable->nentries;
|
||||
/* we don't support long indices */
|
||||
if (s >= 0x7fffffff) {
|
||||
if (w >= 0x7fffffff) {
|
||||
PyErr_SetString(PyExc_ValueError, "too many objects");
|
||||
goto err;
|
||||
}
|
||||
w = (int)s;
|
||||
// Corresponding code should call w_complete() after
|
||||
// writing the object.
|
||||
if (PyCode_Check(v) || PySlice_Check(v)) {
|
||||
w |= 0x80000000LU;
|
||||
}
|
||||
if (_Py_hashtable_set(p->hashtable, Py_NewRef(v),
|
||||
(void *)(uintptr_t)w) < 0) {
|
||||
Py_DECREF(v);
|
||||
|
|
@ -424,6 +431,27 @@ w_ref(PyObject *v, char *flag, WFILE *p)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
w_complete(PyObject *v, WFILE *p)
|
||||
{
|
||||
if (p->version < 3 || p->hashtable == NULL) {
|
||||
return;
|
||||
}
|
||||
if (_PyObject_IsUniquelyReferenced(v)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(p->hashtable, v);
|
||||
if (entry == NULL) {
|
||||
return;
|
||||
}
|
||||
assert(entry != NULL);
|
||||
uintptr_t w = (uintptr_t)entry->value;
|
||||
assert(w & 0x80000000LU);
|
||||
w &= ~0x80000000LU;
|
||||
entry->value = (void *)(uintptr_t)w;
|
||||
}
|
||||
|
||||
static void
|
||||
w_complex_object(PyObject *v, char flag, WFILE *p);
|
||||
|
||||
|
|
@ -673,6 +701,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
w_object(co->co_linetable, p);
|
||||
w_object(co->co_exceptiontable, p);
|
||||
Py_DECREF(co_code);
|
||||
w_complete(v, p);
|
||||
}
|
||||
else if (PyObject_CheckBuffer(v)) {
|
||||
/* Write unknown bytes-like objects as a bytes object */
|
||||
|
|
@ -698,6 +727,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
w_object(slice->start, p);
|
||||
w_object(slice->stop, p);
|
||||
w_object(slice->step, p);
|
||||
w_complete(v, p);
|
||||
}
|
||||
else {
|
||||
W_TYPE(TYPE_UNKNOWN, p);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue