Issue #26146: marshal.loads() now uses the empty frozenset singleton
This commit is contained in:
parent
5ebe2c89fe
commit
1aa78938b0
|
@ -135,6 +135,13 @@ class ContainerTestCase(unittest.TestCase, HelperMixin):
|
|||
for constructor in (set, frozenset):
|
||||
self.helper(constructor(self.d.keys()))
|
||||
|
||||
@support.cpython_only
|
||||
def test_empty_frozenset_singleton(self):
|
||||
# marshal.loads() must reuse the empty frozenset singleton
|
||||
obj = frozenset()
|
||||
obj2 = marshal.loads(marshal.dumps(obj))
|
||||
self.assertIs(obj2, obj)
|
||||
|
||||
|
||||
class BufferTestCase(unittest.TestCase, HelperMixin):
|
||||
|
||||
|
|
|
@ -1266,41 +1266,52 @@ r_object(RFILE *p)
|
|||
PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)");
|
||||
break;
|
||||
}
|
||||
v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL);
|
||||
if (type == TYPE_SET) {
|
||||
R_REF(v);
|
||||
} else {
|
||||
/* must use delayed registration of frozensets because they must
|
||||
* be init with a refcount of 1
|
||||
*/
|
||||
idx = r_ref_reserve(flag, p);
|
||||
if (idx < 0)
|
||||
Py_CLEAR(v); /* signal error */
|
||||
}
|
||||
if (v == NULL)
|
||||
break;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
v2 = r_object(p);
|
||||
if ( v2 == NULL ) {
|
||||
if (!PyErr_Occurred())
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"NULL object in marshal data for set");
|
||||
Py_DECREF(v);
|
||||
v = NULL;
|
||||
if (n == 0 && type == TYPE_FROZENSET) {
|
||||
/* call frozenset() to get the empty frozenset singleton */
|
||||
v = PyObject_CallFunction((PyObject*)&PyFrozenSet_Type, NULL);
|
||||
if (v == NULL)
|
||||
break;
|
||||
}
|
||||
if (PySet_Add(v, v2) == -1) {
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(v2);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
Py_DECREF(v2);
|
||||
R_REF(v);
|
||||
retval = v;
|
||||
}
|
||||
else {
|
||||
v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL);
|
||||
if (type == TYPE_SET) {
|
||||
R_REF(v);
|
||||
} else {
|
||||
/* must use delayed registration of frozensets because they must
|
||||
* be init with a refcount of 1
|
||||
*/
|
||||
idx = r_ref_reserve(flag, p);
|
||||
if (idx < 0)
|
||||
Py_CLEAR(v); /* signal error */
|
||||
}
|
||||
if (v == NULL)
|
||||
break;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
v2 = r_object(p);
|
||||
if ( v2 == NULL ) {
|
||||
if (!PyErr_Occurred())
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"NULL object in marshal data for set");
|
||||
Py_DECREF(v);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
if (PySet_Add(v, v2) == -1) {
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(v2);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
Py_DECREF(v2);
|
||||
}
|
||||
if (type != TYPE_SET)
|
||||
v = r_ref_insert(v, idx, flag, p);
|
||||
retval = v;
|
||||
}
|
||||
if (type != TYPE_SET)
|
||||
v = r_ref_insert(v, idx, flag, p);
|
||||
retval = v;
|
||||
break;
|
||||
|
||||
case TYPE_CODE:
|
||||
|
|
Loading…
Reference in New Issue