bpo-13312: Avoid int underflow in time year. (GH-8912) · python/cpython@d5f017b (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
19 19 # Max year is only limited by the size of C int.
20 20 SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
21 21 TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1
22 -TIME_MINYEAR = -TIME_MAXYEAR - 1
22 +TIME_MINYEAR = -TIME_MAXYEAR - 1 + 1900
23 23
24 24 SEC_TO_US = 10 ** 6
25 25 US_TO_NS = 10 ** 3
@@ -714,12 +714,11 @@ def test_negative(self):
714 714 self.assertEqual(self.yearstr(-123456), '-123456')
715 715 self.assertEqual(self.yearstr(-123456789), str(-123456789))
716 716 self.assertEqual(self.yearstr(-1234567890), str(-1234567890))
717 -self.assertEqual(self.yearstr(TIME_MINYEAR + 1900), str(TIME_MINYEAR + 1900))
718 -# Issue #13312: it may return wrong value for year < TIME_MINYEAR + 1900
719 -# Skip the value test, but check that no error is raised
720 -self.yearstr(TIME_MINYEAR)
721 -# self.assertEqual(self.yearstr(TIME_MINYEAR), str(TIME_MINYEAR))
717 +self.assertEqual(self.yearstr(TIME_MINYEAR), str(TIME_MINYEAR))
718 +# Modules/timemodule.c checks for underflow
722 719 self.assertRaises(OverflowError, self.yearstr, TIME_MINYEAR - 1)
720 +with self.assertRaises(OverflowError):
721 +self.yearstr(-TIME_MAXYEAR - 1)
723 722
724 723
725 724 class TestAsctime4dyear(_TestAsctimeYear, _Test4dYear, unittest.TestCase):
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +Avoids a possible integer underflow (undefined behavior) in the time
2 +module's year handling code when passed a very low negative year value.
Original file line number Diff line number Diff line change
@@ -551,6 +551,12 @@ gettmarg(PyObject *args, struct tm *p, const char *format)
551 551 &p->tm_hour, &p->tm_min, &p->tm_sec,
552 552 &p->tm_wday, &p->tm_yday, &p->tm_isdst))
553 553 return 0;
554 +
555 +if (y < INT_MIN + 1900) {
556 +PyErr_SetString(PyExc_OverflowError, "year out of range");
557 +return 0;
558 + }
559 +
554 560 p->tm_year = y - 1900;
555 561 p->tm_mon--;
556 562 p->tm_wday = (p->tm_wday + 1) % 7;