summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSkip Montanaro <skip@pobox.com>2005-05-20 03:07:06 (GMT)
committerSkip Montanaro <skip@pobox.com>2005-05-20 03:07:06 (GMT)
commitbbf12ba7b20059324cf10e26aa98bc0fa405ad3d (patch)
treefde2a9dead8987c5ddffe6cab4a997322483b0ac
parent7961aa6135e5a26c1cc14bbcaa2668d2ec98b0b9 (diff)
downloadcpython-bbf12ba7b20059324cf10e26aa98bc0fa405ad3d.zip
cpython-bbf12ba7b20059324cf10e26aa98bc0fa405ad3d.tar.gz
cpython-bbf12ba7b20059324cf10e26aa98bc0fa405ad3d.tar.bz2
Disallow opening files with modes 'aU' or 'wU' as specified by PEP
278. Closes bug 967182.
-rw-r--r--Lib/test/test_file.py10
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/fileobject.c51
3 files changed, 64 insertions, 0 deletions
diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py
index af8eadf..2d2d9c1 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 4d8f3b1..77e059e 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 c08345c..7e40547 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. */