From eb8bf6dfc1c8ea594b69c8f8901a285763a660a5 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google]" Date: Fri, 24 Aug 2018 17:25:31 -0700 Subject: [PATCH 1/3] bpo-13312: Avoid int underflow in time year. Avoids an integer underflow in the time module's year handling code. --- Lib/test/test_time.py | 11 +++++------ Modules/timemodule.c | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 7354b969907b16..9a84f92301e5ad 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -19,7 +19,7 @@ # Max year is only limited by the size of C int. SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4 TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1 -TIME_MINYEAR = -TIME_MAXYEAR - 1 +TIME_MINYEAR = -TIME_MAXYEAR - 1 + 1900 SEC_TO_US = 10 ** 6 US_TO_NS = 10 ** 3 @@ -714,12 +714,11 @@ def test_negative(self): self.assertEqual(self.yearstr(-123456), '-123456') self.assertEqual(self.yearstr(-123456789), str(-123456789)) self.assertEqual(self.yearstr(-1234567890), str(-1234567890)) - self.assertEqual(self.yearstr(TIME_MINYEAR + 1900), str(TIME_MINYEAR + 1900)) - # Issue #13312: it may return wrong value for year < TIME_MINYEAR + 1900 - # Skip the value test, but check that no error is raised - self.yearstr(TIME_MINYEAR) - # self.assertEqual(self.yearstr(TIME_MINYEAR), str(TIME_MINYEAR)) + self.assertEqual(self.yearstr(TIME_MINYEAR), str(TIME_MINYEAR)) + # Modules/timemodule.c checks for underflow self.assertRaises(OverflowError, self.yearstr, TIME_MINYEAR - 1) + with self.assertRaises(OverflowError): + self.yearstr(-TIME_MAXYEAR - 1) class TestAsctime4dyear(_TestAsctimeYear, _Test4dYear, unittest.TestCase): diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 998216cc8fdbdf..dbe2fbaf07967c 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -551,6 +551,12 @@ gettmarg(PyObject *args, struct tm *p, const char *format) &p->tm_hour, &p->tm_min, &p->tm_sec, &p->tm_wday, &p->tm_yday, &p->tm_isdst)) return 0; + + if (y < INT_MIN + 1900) { + PyErr_SetString(PyExc_OverflowError, "year out of range"); + return 0; + } + p->tm_year = y - 1900; p->tm_mon--; p->tm_wday = (p->tm_wday + 1) % 7; From f50048ee3f8b7522fc6a5b29c66b60c39d8bfb0b Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google]" Date: Fri, 24 Aug 2018 17:31:32 -0700 Subject: [PATCH 2/3] Add a NEWS entry. --- .../next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst diff --git a/Misc/NEWS.d/next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst b/Misc/NEWS.d/next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst new file mode 100644 index 00000000000000..dc906696a53ed4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst @@ -0,0 +1,2 @@ +Avoids a possible integer underflow (undefined behavior) in the time +module's year handling code when passed a very low negative year value. From 03627bdd30384d18dd28faaa9969b001216dc0f2 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith [Google]" Date: Fri, 24 Aug 2018 17:46:02 -0700 Subject: [PATCH 3/3] Leading whitespace fix. --- Lib/test/test_time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 9a84f92301e5ad..9acd1d497ee892 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -718,7 +718,7 @@ def test_negative(self): # Modules/timemodule.c checks for underflow self.assertRaises(OverflowError, self.yearstr, TIME_MINYEAR - 1) with self.assertRaises(OverflowError): - self.yearstr(-TIME_MAXYEAR - 1) + self.yearstr(-TIME_MAXYEAR - 1) class TestAsctime4dyear(_TestAsctimeYear, _Test4dYear, unittest.TestCase):