From bbf12ba7b20059324cf10e26aa98bc0fa405ad3d Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Fri, 20 May 2005 03:07:06 +0000 Subject: [PATCH] Disallow opening files with modes 'aU' or 'wU' as specified by PEP 278. Closes bug 967182. --- Lib/test/test_file.py | 10 +++++++++ Misc/NEWS | 3 +++ Objects/fileobject.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index af8eadfb971..2d2d9c1c219 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -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') diff --git a/Misc/NEWS b/Misc/NEWS index 4d8f3b15bd2..77e059e69c9 100644 --- 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 diff --git a/Objects/fileobject.c b/Objects/fileobject.c index c08345c04d3..7e40547e993 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -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. */