Disallow opening files with modes 'aU' or 'wU' as specified by PEP
278. Closes bug 967182.
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 @@
         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 @@
 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 @@
 	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 @@
 	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. */