]> granicus.if.org Git - python/commitdiff
bpo-13312: Avoid int underflow in time year. (GH-8912)
authorGregory P. Smith <greg@krypto.org>
Sat, 25 Aug 2018 01:08:50 +0000 (18:08 -0700)
committerGitHub <noreply@github.com>
Sat, 25 Aug 2018 01:08:50 +0000 (18:08 -0700)
Avoids an integer underflow in the time module's year handling code.

Lib/test/test_time.py
Misc/NEWS.d/next/Library/2018-08-24-17-31-27.bpo-13312.6hA5La.rst [new file with mode: 0644]
Modules/timemodule.c

index 7354b969907b16a4c4b629d95e990d4196ad0388..9acd1d497ee8924c82e2828c3c3ad5a8072b57ce 100644 (file)
@@ -19,7 +19,7 @@ except ImportError:
 # 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 @@ class _Test4dYear:
         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/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 (file)
index 0000000..dc90669
--- /dev/null
@@ -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.
index 998216cc8fdbdf54f3044d8b287be0f99825bb46..dbe2fbaf07967c55c480775ce72b2e339a85ae3b 100644 (file)
@@ -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;