diff options
-rw-r--r-- | Lib/test/test_datetime.py | 34 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Modules/datetimemodule.c | 9 |
3 files changed, 41 insertions, 6 deletions
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index 347b1a9..f7fec57 100644 --- a/Lib/test/test_datetime.py +++ b/Lib/test/test_datetime.py @@ -510,6 +510,9 @@ class TestDateOnly(unittest.TestCase): dt2 = dt - delta self.assertEqual(dt2, dt - days) +class SubclassDate(date): + sub_var = 1 + class TestDate(HarmlessMixedComparison): # Tests here should pass for both dates and datetimes, except for a # few tests that TestDateTime overrides. @@ -1029,6 +1032,15 @@ class TestDate(HarmlessMixedComparison): self.assertEqual(dt1.toordinal(), dt2.toordinal()) self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month - 7) + def test_pickling_subclass_date(self): + + args = 6, 7, 23 + orig = SubclassDate(*args) + for pickler, unpickler, proto in pickle_choices: + green = pickler.dumps(orig, proto) + derived = unpickler.loads(green) + self.assertEqual(orig, derived) + def test_backdoor_resistance(self): # For fast unpickling, the constructor accepts a pickle string. # This is a low-overhead backdoor. A user can (by intent or @@ -1053,6 +1065,9 @@ class TestDate(HarmlessMixedComparison): ############################################################################# # datetime tests +class SubclassDatetime(datetime): + sub_var = 1 + class TestDateTime(TestDate): theclass = datetime @@ -1296,6 +1311,14 @@ class TestDateTime(TestDate): self.assertEqual(b.month, 2) self.assertEqual(b.day, 7) + def test_pickling_subclass_datetime(self): + args = 6, 7, 23, 20, 59, 1, 64**2 + orig = SubclassDatetime(*args) + for pickler, unpickler, proto in pickle_choices: + green = pickler.dumps(orig, proto) + derived = unpickler.loads(green) + self.assertEqual(orig, derived) + def test_more_compare(self): # The test_compare() inherited from TestDate covers the error cases. # We just want to test lexicographic ordering on the members datetime @@ -1500,6 +1523,9 @@ class TestDateTime(TestDate): self.assertEqual(dt2.newmeth(-7), dt1.year + dt1.month + dt1.second - 7) +class SubclassTime(time): + sub_var = 1 + class TestTime(HarmlessMixedComparison): theclass = time @@ -1700,6 +1726,14 @@ class TestTime(HarmlessMixedComparison): derived = unpickler.loads(green) self.assertEqual(orig, derived) + def test_pickling_subclass_time(self): + args = 20, 59, 16, 64**2 + orig = SubclassTime(*args) + for pickler, unpickler, proto in pickle_choices: + green = pickler.dumps(orig, proto) + derived = unpickler.loads(green) + self.assertEqual(orig, derived) + def test_bool(self): cls = self.theclass self.failUnless(cls(1)) @@ -12,6 +12,10 @@ What's New in Python 2.4 alpha 1? Core and builtins ----------------- +- Bug #952807: Unpickling pickled instances of subclasses of + datetime.date, datetime.datetime and datetime.time could yield insane + objects. Thanks to Jiwon Seo for a fix. + - Bug #845802: Python crashes when __init__.py is a directory. - Unicode objects received two new methods: iswide() and width(). diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 225a6b1..7f38d1a 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -2206,7 +2206,7 @@ date_new(PyTypeObject *type, PyObject *args, PyObject *kw) { PyDateTime_Date *me; - me = PyObject_New(PyDateTime_Date, type); + me = (PyDateTime_Date *) (type->tp_alloc(type, 0)); if (me != NULL) { char *pdata = PyString_AS_STRING(state); memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE); @@ -3049,8 +3049,7 @@ time_new(PyTypeObject *type, PyObject *args, PyObject *kw) } } aware = (char)(tzinfo != Py_None); - me = (PyDateTime_Time *) time_alloc(&PyDateTime_TimeType, - aware); + me = (PyDateTime_Time *) (type->tp_alloc(type, aware)); if (me != NULL) { char *pdata = PyString_AS_STRING(state); @@ -3572,9 +3571,7 @@ datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) } } aware = (char)(tzinfo != Py_None); - me = (PyDateTime_DateTime *) datetime_alloc( - &PyDateTime_DateTimeType, - aware); + me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware)); if (me != NULL) { char *pdata = PyString_AS_STRING(state); |