]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Disallow opening files with modes 'aU' or 'wU' as specified by PEP
authorSkip Montanaro <skip@pobox.com>
Fri, 20 May 2005 03:07:06 +0000 (03:07 +0000)
committerSkip Montanaro <skip@pobox.com>
Fri, 20 May 2005 03:07:06 +0000 (03:07 +0000)
278. Closes bug 967182.

Lib/test/test_file.py
Misc/NEWS
Objects/fileobject.c

index af8eadfb971360e825ddcfeff0c115d985ad7e13..2d2d9c1c219ab11bac954ca9f6afa8057896a666 100644 (file)
@@ -40,6 +40,16 @@ for attr in 'name', 'mode', 'closed':
         raise TestFailed('expected exception setting file attr %r' % attr)
 f.close()
 
+# check invalid mode strings
+for mode in ("", "aU", "wU+"):
+    try:
+        f = file(TESTFN, mode)
+    except ValueError:
+        pass
+    else:
+        f.close()
+        raise TestFailed('%r is an invalid file mode' % mode)
+
 # verify writelines with instance sequence
 l = UserList(['1', '2'])
 f = open(TESTFN, 'wb')
index 4d8f3b15bd25ca2f9ad650bcf10b2196007e60cb..77e059e69c95e1aa5ac469543a443221db02174f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1?
 Core and builtins
 -----------------
 
+- bug #967182: disallow opening files with 'wU' or 'aU' as specified by PEP
+  278.
+
 - patch #1109424: int, long, float, complex, and unicode now check for the
   proper magic slot for type conversions when subclassed.  Previously the
   magic slot was ignored during conversion.  Semantics now match the way
index c08345c04d395f69f1c412b296083f5fc2bd366d..7e40547e993f59303d24c695449c530d36b32b16 100644 (file)
@@ -128,6 +128,54 @@ fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
        return (PyObject *) f;
 }
 
+/* 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
+   universal newline support is expressly forbidden by PEP 278. */
+/* zero return is kewl - one is un-kewl */
+static int
+check_the_mode(char *mode)
+{
+       unsigned int len = strlen(mode);
+
+       switch (len) {
+       case 0:
+               PyErr_SetString(PyExc_ValueError, "empty mode string");
+               return 1;
+
+       /* reject wU, aU */
+       case 2:
+               switch (mode[0]) {
+               case 'w':
+               case 'a':
+                       if (mode[1] == 'U') {
+                               PyErr_SetString(PyExc_ValueError,
+                                               "invalid mode string");
+                               return 1;
+                       }
+                       break;
+               }
+               break;
+
+       /* reject w+U, a+U, wU+, aU+ */
+       case 3:
+               switch (mode[0]) {
+               case 'w':
+               case 'a':
+                       if ((mode[1] == '+' && mode[2] == 'U') ||
+                           (mode[1] == 'U' && mode[2] == '+')) {
+                               PyErr_SetString(PyExc_ValueError,
+                                               "invalid mode string");
+                               return 1;
+                       }
+                       break;
+               }
+               break;
+       }
+
+       return 0;
+}
+
 static PyObject *
 open_the_file(PyFileObject *f, char *name, char *mode)
 {
@@ -142,6 +190,9 @@ open_the_file(PyFileObject *f, char *name, char *mode)
        assert(mode != NULL);
        assert(f->f_fp == NULL);
 
+       if (check_the_mode(mode))
+               return NULL;
+
        /* rexec.py can't stop a user from getting the file() constructor --
           all they have to do is get *any* file object f, and then do
           type(f).  Here we prevent them from doing damage with it. */