diff options
-rw-r--r-- | Lib/test/test_file.py | 2 | ||||
-rw-r--r-- | Modules/timemodule.c | 17 | ||||
-rw-r--r-- | Objects/fileobject.c | 89 |
3 files changed, 106 insertions, 2 deletions
diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index b4f494b..a134a89 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -154,7 +154,7 @@ class OtherFileTests(unittest.TestCase): for name in (TESTFN, unicode(TESTFN), unicode(TESTFN + '\t')): try: f = open(name, "rr") - except IOError: + except (IOError, ValueError): pass else: f.close() diff --git a/Modules/timemodule.c b/Modules/timemodule.c index e8de2c5..2f4092d 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -470,6 +470,23 @@ time_strftime(PyObject *self, PyObject *args) return NULL; } +#ifdef MS_WINDOWS + /* check that the format string contains only valid directives */ + for(outbuf = strchr(fmt, '%'); + outbuf != NULL; + outbuf = strchr(outbuf+2, '%')) + { + if (outbuf[1]=='#') + ++outbuf; /* not documented by python, */ + if (outbuf[1]=='\0' || + !strchr("aAbBcdfHIjmMpSUwWxXyYzZ%", outbuf[1])) + { + PyErr_SetString(PyExc_ValueError, "Invalid format string"); + return 0; + } + } +#endif + fmtlen = strlen(fmt); /* I hate these functions that presume you know how big the output diff --git a/Objects/fileobject.c b/Objects/fileobject.c index e01f38e..77724d4 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -181,6 +181,87 @@ fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode, return (PyObject *) f; } +#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) +#define Py_VERIFY_WINNT +/* The CRT on windows compiled with Visual Studio 2005 and higher may + * assert if given invalid mode strings. This is all fine and well + * in static languages like C where the mode string is typcially hard + * coded. But in Python, were we pass in the mode string from the user, + * we need to verify it first manually + */ +static int _PyVerify_Mode_WINNT(const char *mode) +{ + /* See if mode string is valid on Windows to avoid hard assertions */ + /* remove leading spacese */ + int singles = 0; + int pairs = 0; + int encoding = 0; + const char *s, *c; + + while(*mode == ' ') /* strip initial spaces */ + ++mode; + if (!strchr("rwa", *mode)) /* must start with one of these */ + return 0; + while (*++mode) { + if (*mode == ' ' || *mode == 'N') /* ignore spaces and N */ + continue; + s = "+TD"; /* each of this can appear only once */ + c = strchr(s, *mode); + if (c) { + ptrdiff_t idx = s-c; + if (singles & (1<<idx)) + return 0; + singles |= (1<<idx); + continue; + } + s = "btcnSR"; /* only one of each letter in the pairs allowed */ + c = strchr(s, *mode); + if (c) { + ptrdiff_t idx = (s-c)/2; + if (pairs & (1<<idx)) + return 0; + pairs |= (1<<idx); + continue; + } + if (*mode == ',') { + encoding = 1; + break; + } + return 0; /* found an invalid char */ + } + + if (encoding) { + char *e[] = {"UTF-8", "UTF-16LE", "UNICODE"}; + while (*mode == ' ') + ++mode; + /* find 'ccs =' */ + if (strncmp(mode, "ccs", 3)) + return 0; + mode += 3; + while (*mode == ' ') + ++mode; + if (*mode != '=') + return 0; + while (*mode == ' ') + ++mode; + for(encoding = 0; encoding<_countof(e); ++encoding) { + size_t l = strlen(e[encoding]); + if (!strncmp(mode, e[encoding], l)) { + mode += l; /* found a valid encoding */ + break; + } + } + if (encoding == _countof(e)) + return 0; + } + /* skip trailing spaces */ + while (*mode == ' ') + ++mode; + + return *mode == '\0'; /* must be at the end of the string */ +} +#endif + /* check for known incorrect mode strings - problem is, platforms are free to accept any mode characters they like and are supposed to ignore stuff they don't understand... write or append mode with @@ -223,7 +304,13 @@ _PyFile_SanitizeMode(char *mode) "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode); return -1; } - +#ifdef Py_VERIFY_WINNT + /* additional checks on NT with visual studio 2005 and higher */ + if (!_PyVerify_Mode_WINNT(mode)) { + PyErr_Format(PyExc_ValueError, "Invalid mode ('%.50s')", mode); + return -1; + } +#endif return 0; } |