Kaydet (Commit) 12e94200 authored tarafından Raymond Hettinger's avatar Raymond Hettinger

Fix marshal's incorrect handling of subclasses of builtin types (backport candidate).

üst 9b847b43
......@@ -44,12 +44,6 @@ and dictionaries are only supported as long as the values contained therein are
themselves supported; and recursive lists and dictionaries should not be written
(they will cause infinite loops).
.. warning::
Some unsupported types such as subclasses of builtins will appear to marshal
and unmarshal correctly, but in fact, their type will change and the
additional subclass functionality and instance attributes will be lost.
.. warning::
On machines where C's ``long int`` type has more than 32 bits (such as the
......
......@@ -244,6 +244,17 @@ class BugsTestCase(unittest.TestCase):
last.append([0])
self.assertRaises(ValueError, marshal.dumps, head)
def test_exact_type_match(self):
# Former bug:
# >>> class Int(int): pass
# >>> type(loads(dumps(Int())))
# <type 'int'>
for typ in (int, long, float, complex, tuple, list, dict, set, frozenset):
# Note: str and unicode sublclasses are not tested because they get handled
# by marshal's routines for objects supporting the buffer API.
subtyp = type('subtyp', (typ,), {})
self.assertRaises(ValueError, marshal.dumps, subtyp())
def test_main():
test_support.run_unittest(IntTestCase,
FloatTestCase,
......
......@@ -812,6 +812,10 @@ Library
Extension Modules
-----------------
- Marshal.dumps() now expects exact type matches for int, long, float, complex,
tuple, list, dict, set, and frozenset. Formerly, it would silently miscode
subclasses of those types. Now, it raises a ValueError instead.
- Patch #1388440: Add set_completion_display_matches_hook and
get_completion_type to readline.
......
......@@ -144,7 +144,7 @@ w_object(PyObject *v, WFILE *p)
else if (v == Py_True) {
w_byte(TYPE_TRUE, p);
}
else if (PyInt_Check(v)) {
else if (PyInt_CheckExact(v)) {
long x = PyInt_AS_LONG((PyIntObject *)v);
#if SIZEOF_LONG > 4
long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);
......@@ -159,7 +159,7 @@ w_object(PyObject *v, WFILE *p)
w_long(x, p);
}
}
else if (PyLong_Check(v)) {
else if (PyLong_CheckExact(v)) {
PyLongObject *ob = (PyLongObject *)v;
w_byte(TYPE_LONG, p);
n = ob->ob_size;
......@@ -169,7 +169,7 @@ w_object(PyObject *v, WFILE *p)
for (i = 0; i < n; i++)
w_short(ob->ob_digit[i], p);
}
else if (PyFloat_Check(v)) {
else if (PyFloat_CheckExact(v)) {
if (p->version > 1) {
unsigned char buf[8];
if (_PyFloat_Pack8(PyFloat_AsDouble(v),
......@@ -190,7 +190,7 @@ w_object(PyObject *v, WFILE *p)
}
}
#ifndef WITHOUT_COMPLEX
else if (PyComplex_Check(v)) {
else if (PyComplex_CheckExact(v)) {
if (p->version > 1) {
unsigned char buf[8];
if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),
......@@ -236,7 +236,7 @@ w_object(PyObject *v, WFILE *p)
}
}
#endif
else if (PyString_Check(v)) {
else if (PyString_CheckExact(v)) {
if (p->strings && PyString_CHECK_INTERNED(v)) {
PyObject *o = PyDict_GetItem(p->strings, v);
if (o) {
......@@ -273,7 +273,7 @@ w_object(PyObject *v, WFILE *p)
w_string(PyString_AS_STRING(v), (int)n, p);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(v)) {
else if (PyUnicode_CheckExact(v)) {
PyObject *utf8;
utf8 = PyUnicode_AsUTF8String(v);
if (utf8 == NULL) {
......@@ -293,7 +293,7 @@ w_object(PyObject *v, WFILE *p)
Py_DECREF(utf8);
}
#endif
else if (PyTuple_Check(v)) {
else if (PyTuple_CheckExact(v)) {
w_byte(TYPE_TUPLE, p);
n = PyTuple_Size(v);
w_long((long)n, p);
......@@ -301,7 +301,7 @@ w_object(PyObject *v, WFILE *p)
w_object(PyTuple_GET_ITEM(v, i), p);
}
}
else if (PyList_Check(v)) {
else if (PyList_CheckExact(v)) {
w_byte(TYPE_LIST, p);
n = PyList_GET_SIZE(v);
w_long((long)n, p);
......@@ -309,7 +309,7 @@ w_object(PyObject *v, WFILE *p)
w_object(PyList_GET_ITEM(v, i), p);
}
}
else if (PyDict_Check(v)) {
else if (PyDict_CheckExact(v)) {
Py_ssize_t pos;
PyObject *key, *value;
w_byte(TYPE_DICT, p);
......@@ -321,7 +321,7 @@ w_object(PyObject *v, WFILE *p)
}
w_object((PyObject *)NULL, p);
}
else if (PyAnySet_Check(v)) {
else if (PyAnySet_CheckExact(v)) {
PyObject *value, *it;
if (PyObject_TypeCheck(v, &PySet_Type))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment