From d8b9346a0d1f0bf99fbb0f71007f9de81b8d1088 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Mon, 7 Jun 2004 23:17:48 +0000 Subject: SF 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. --- Lib/test/test_datetime.py | 33 +++++++++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 6 +++++- Modules/datetimemodule.c | 9 +++------ 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py index c6dbb48..cb48b8b 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,10 +1032,21 @@ 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) + ############################################################################# # datetime tests +class SubclassDatetime(datetime): + sub_var = 1 + class TestDateTime(TestDate): theclass = datetime @@ -1276,6 +1290,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 @@ -1480,6 +1502,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 @@ -1680,6 +1705,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)) diff --git a/Misc/ACKS b/Misc/ACKS index de27616..38763d1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -490,6 +490,7 @@ Barry Scott Steven Scott Nick Seidenman Fred Sells +Jiwon Seo Denis Severson Ha Shao Bruce Sherwood diff --git a/Misc/NEWS b/Misc/NEWS index 46c5350..e917e88 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.3.5? 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 crashed when __init__.py is a directory. Extension modules @@ -23,7 +27,7 @@ Extension modules - Bug #841757: xmlrpclib failed on structs with Unicode keys. -- Bug #954364: inspect.getframeinfo() sometimes produces incorrect traceback +- Bug #954364: inspect.getframeinfo() sometimes produces incorrect traceback line numbers What's New in Python 2.3.4 (final)? diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c index 21e770f..80d54e1 100644 --- a/Modules/datetimemodule.c +++ b/Modules/datetimemodule.c @@ -2199,7 +2199,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); @@ -3042,8 +3042,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); @@ -3564,9 +3563,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); -- cgit v0.12