[Python-checkins] cpython (3.5): Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as

serhiy.storchaka python-checkins at python.org
Sat Jun 18 06:56:38 EDT 2016


https://hg.python.org/cpython/rev/2e48c2c4c733
changeset:   102086:2e48c2c4c733
branch:      3.5
parent:      102084:4c361e189747
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sat Jun 18 13:53:36 2016 +0300
summary:
  Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as
an iterable of integers. Now only strings and byte-like objects are accepted.

files:
  Lib/test/test_compile.py   |   7 +++++++
  Lib/test/test_parser.py    |  16 ++++++++++++++++
  Lib/test/test_symtable.py  |   6 ++++++
  Lib/test/test_zipimport.py |  15 +++++++++++++++
  Misc/NEWS                  |  11 +++++++++++
  Objects/unicodeobject.c    |   8 +++++++-
  6 files changed, 62 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -472,6 +472,13 @@
         d = {f(): f(), f(): f()}
         self.assertEqual(d, {1: 2, 3: 4})
 
+    def test_compile_filename(self):
+        for filename in ('file.py', b'file.py',
+                         bytearray(b'file.py'), memoryview(b'file.py')):
+            code = compile('pass', filename, 'exec')
+            self.assertEqual(code.co_filename, 'file.py')
+        self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')
+
     @support.cpython_only
     def test_same_filename_used(self):
         s = """def f(): pass\ndef g(): pass"""
diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py
--- a/Lib/test/test_parser.py
+++ b/Lib/test/test_parser.py
@@ -627,6 +627,22 @@
         code2 = parser.compilest(st)
         self.assertEqual(eval(code2), -3)
 
+    def test_compile_filename(self):
+        st = parser.expr('a + 5')
+        code = parser.compilest(st)
+        self.assertEqual(code.co_filename, '<syntax-tree>')
+        code = st.compile()
+        self.assertEqual(code.co_filename, '<syntax-tree>')
+        for filename in ('file.py', b'file.py',
+                         bytearray(b'file.py'), memoryview(b'file.py')):
+            code = parser.compilest(st, filename)
+            self.assertEqual(code.co_filename, 'file.py')
+            code = st.compile(filename)
+            self.assertEqual(code.co_filename, 'file.py')
+        self.assertRaises(TypeError, parser.compilest, st, list(b'file.py'))
+        self.assertRaises(TypeError, st.compile, list(b'file.py'))
+
+
 class ParserStackLimitTestCase(unittest.TestCase):
     """try to push the parser to/over its limits.
     see http://bugs.python.org/issue1881 for a discussion
diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py
--- a/Lib/test/test_symtable.py
+++ b/Lib/test/test_symtable.py
@@ -157,6 +157,12 @@
                 self.fail("no SyntaxError for %r" % (brokencode,))
         checkfilename("def f(x): foo)(")  # parse-time
         checkfilename("def f(x): global x")  # symtable-build-time
+        symtable.symtable("pass", b"spam", "exec")
+        with self.assertRaises(TypeError):
+            symtable.symtable("pass", bytearray(b"spam"), "exec")
+        symtable.symtable("pass", memoryview(b"spam"), "exec")
+        with self.assertRaises(TypeError):
+            symtable.symtable("pass", list(b"spam"), "exec")
 
     def test_eval(self):
         symbols = symtable.symtable("42", "?", "eval")
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py
--- a/Lib/test/test_zipimport.py
+++ b/Lib/test/test_zipimport.py
@@ -600,6 +600,19 @@
         finally:
             os.remove(filename)
 
+    def testBytesPath(self):
+        filename = support.TESTFN + ".zip"
+        self.addCleanup(support.unlink, filename)
+        with ZipFile(filename, "w") as z:
+            zinfo = ZipInfo(TESTMOD + ".py", time.localtime(NOW))
+            zinfo.compress_type = self.compression
+            z.writestr(zinfo, test_src)
+
+        zipimport.zipimporter(filename)
+        zipimport.zipimporter(os.fsencode(filename))
+        zipimport.zipimporter(bytearray(os.fsencode(filename)))
+        zipimport.zipimporter(memoryview(os.fsencode(filename)))
+
 
 @support.requires_zlib
 class CompressedZipImportTestCase(UncompressedZipImportTestCase):
@@ -620,6 +633,8 @@
     def testBadArgs(self):
         self.assertRaises(TypeError, zipimport.zipimporter, None)
         self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
+        self.assertRaises(TypeError, zipimport.zipimporter,
+                          list(os.fsencode(TESTMOD)))
 
     def testFilenameTooLong(self):
         self.assertZipFailure('A' * 33000)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@
 Library
 -------
 
+- Issue #26754: Some functions (compile() etc) accepted a filename argument
+  encoded as an iterable of integers. Now only strings and byte-like objects
+  are accepted.
+
 - Issue #27048: Prevents distutils failing on Windows when environment
   variables contain non-ASCII characters
 
@@ -43,6 +47,13 @@
 
 - Issue #26930: Update Windows builds to use OpenSSL 1.0.2h.
 
+C API
+-----
+
+- Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as
+  an iterable of integers. Now only strings and byte-like objects are accepted.
+
+
 What's New in Python 3.5.2 final?
 =================================
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3666,7 +3666,7 @@
         output = arg;
         Py_INCREF(output);
     }
-    else {
+    else if (PyObject_CheckBuffer(arg)) {
         arg = PyBytes_FromObject(arg);
         if (!arg)
             return 0;
@@ -3681,6 +3681,12 @@
             return 0;
         }
     }
+    else {
+        PyErr_Format(PyExc_TypeError,
+                     "path should be string or bytes, not %.200s",
+                     Py_TYPE(arg)->tp_name);
+        return 0;
+    }
     if (PyUnicode_READY(output) == -1) {
         Py_DECREF(output);
         return 0;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list