summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2004-06-07 23:04:33 (GMT)
committerTim Peters <tim.peters@gmail.com>2004-06-07 23:04:33 (GMT)
commit604c013ef2747e70fa5f3140eb36d9969606070e (patch)
tree9678f32052d99737e23e085d242f88a93b125362
parentd348193ff2bbf8b007f9cabd7fc81ab3491464e3 (diff)
downloadcpython-604c013ef2747e70fa5f3140eb36d9969606070e.zip
cpython-604c013ef2747e70fa5f3140eb36d9969606070e.tar.gz
cpython-604c013ef2747e70fa5f3140eb36d9969606070e.tar.bz2
SF 952807: Unpickling pickled instances of subclasses of datetime.date,
datetime.datetime and datetime.time could yield insane objects. Thanks to Jiwon Seo for the fix. Bugfix candidate. I'll backport it to 2.3.
-rw-r--r--Lib/test/test_datetime.py34
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/datetimemodule.c9
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))
diff --git a/Misc/NEWS b/Misc/NEWS
index fe6df61..cfd296e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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);