summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_file.py2
-rw-r--r--Modules/timemodule.c17
-rw-r--r--Objects/fileobject.c89
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;
}