[Python-checkins] cpython (3.5): Issue #24917: time_strftime() buffer over-read.

steve.dower python-checkins at python.org
Mon Sep 7 07:38:01 CEST 2015


https://hg.python.org/cpython/rev/c31dad22c80d
changeset:   97729:c31dad22c80d
branch:      3.5
user:        Steve Dower <steve.dower at microsoft.com>
date:        Sun Sep 06 19:20:51 2015 -0700
summary:
  Issue #24917: time_strftime() buffer over-read.

files:
  Lib/test/test_time.py |  13 +++++++++++++
  Misc/NEWS             |   2 ++
  Modules/timemodule.c  |  16 ++++++++++------
  3 files changed, 25 insertions(+), 6 deletions(-)


diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -174,6 +174,19 @@
     def test_strftime_bounding_check(self):
         self._bounds_checking(lambda tup: time.strftime('', tup))
 
+    def test_strftime_format_check(self):
+        # Test that strftime does not crash on invalid format strings
+        # that may trigger a buffer overread. When not triggered,
+        # strftime may succeed or raise ValueError depending on
+        # the platform.
+        for x in [ '', 'A', '%A', '%AA' ]:
+            for y in range(0x0, 0x10):
+                for z in [ '%', 'A%', 'AA%', '%A%', 'A%A%', '%#' ]:
+                    try:
+                        time.strftime(x * y + z)
+                    except ValueError:
+                        pass
+
     def test_default_values_for_zero(self):
         # Make sure that using all zeros uses the proper default
         # values.  No test for daylight savings since strftime() does
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -20,6 +20,8 @@
 Library
 -------
 
+- Issue #24917: time_strftime() buffer over-read.
+
 - Issue #24748: To resolve a compatibility problem found with py2exe and
   pywin32, imp.load_dynamic() once again ignores previously loaded modules
   to support Python modules replacing themselves with extension modules.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -610,14 +610,15 @@
 
 #if defined(MS_WINDOWS) && !defined(HAVE_WCSFTIME)
     /* check that the format string contains only valid directives */
-    for(outbuf = strchr(fmt, '%');
+    for (outbuf = strchr(fmt, '%');
         outbuf != NULL;
         outbuf = strchr(outbuf+2, '%'))
     {
-        if (outbuf[1]=='#')
+        if (outbuf[1] == '#')
             ++outbuf; /* not documented by python, */
-        if ((outbuf[1] == 'y') && buf.tm_year < 0)
-        {
+        if (outbuf[1] == '\0')
+            break;
+        if ((outbuf[1] == 'y') && buf.tm_year < 0) {
             PyErr_SetString(PyExc_ValueError,
                         "format %y requires year >= 1900 on Windows");
             Py_DECREF(format);
@@ -625,10 +626,12 @@
         }
     }
 #elif (defined(_AIX) || defined(sun)) && defined(HAVE_WCSFTIME)
-    for(outbuf = wcschr(fmt, '%');
+    for (outbuf = wcschr(fmt, '%');
         outbuf != NULL;
         outbuf = wcschr(outbuf+2, '%'))
     {
+        if (outbuf[1] == L'\0')
+            break;
         /* Issue #19634: On AIX, wcsftime("y", (1899, 1, 1, 0, 0, 0, 0, 0, 0))
            returns "0/" instead of "99" */
         if (outbuf[1] == L'y' && buf.tm_year < 0) {
@@ -659,7 +662,8 @@
 #if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
         err = errno;
 #endif
-        if (buflen > 0 || i >= 256 * fmtlen) {
+        if (buflen > 0 || fmtlen == 0 ||
+            (fmtlen > 4 && i >= 256 * fmtlen)) {
             /* If the buffer is 256 times as long as the format,
                it's probably not failing for lack of room!
                More likely, the format yields an empty result,

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list