changeset: 102087:e18ac7370113 parent: 102085:79a3aff60e37 parent: 102086:2e48c2c4c733 user: Serhiy Storchaka date: Sat Jun 18 13:56:16 2016 +0300 files: Lib/test/test_parser.py Lib/test/test_zipimport.py Misc/NEWS Objects/unicodeobject.c description: Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as an iterable of integers. Now only strings and byte-like objects are accepted. diff -r 79a3aff60e37 -r e18ac7370113 Lib/test/test_compile.py --- a/Lib/test/test_compile.py Sat Jun 18 08:20:22 2016 +0000 +++ b/Lib/test/test_compile.py Sat Jun 18 13:56:16 2016 +0300 @@ -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 -r 79a3aff60e37 -r e18ac7370113 Lib/test/test_parser.py --- a/Lib/test/test_parser.py Sat Jun 18 08:20:22 2016 +0000 +++ b/Lib/test/test_parser.py Sat Jun 18 13:56:16 2016 +0300 @@ -626,6 +626,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, '') + code = st.compile() + self.assertEqual(code.co_filename, '') + 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 -r 79a3aff60e37 -r e18ac7370113 Lib/test/test_symtable.py --- a/Lib/test/test_symtable.py Sat Jun 18 08:20:22 2016 +0000 +++ b/Lib/test/test_symtable.py Sat Jun 18 13:56:16 2016 +0300 @@ -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 -r 79a3aff60e37 -r e18ac7370113 Lib/test/test_zipimport.py --- a/Lib/test/test_zipimport.py Sat Jun 18 08:20:22 2016 +0000 +++ b/Lib/test/test_zipimport.py Sat Jun 18 13:56:16 2016 +0300 @@ -619,6 +619,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): @@ -639,6 +652,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 -r 79a3aff60e37 -r e18ac7370113 Misc/NEWS --- a/Misc/NEWS Sat Jun 18 08:20:22 2016 +0000 +++ b/Misc/NEWS Sat Jun 18 13:56:16 2016 +0300 @@ -10,6 +10,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 #26536: socket.ioctl now supports SIO_LOOPBACK_FAST_PATH. Patch by Daniel Stokes. @@ -52,6 +56,12 @@ - Issue #27310: Fix IDLE.app failure to launch on OS X due to vestigial import. +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. + Build ----- diff -r 79a3aff60e37 -r e18ac7370113 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Sat Jun 18 08:20:22 2016 +0000 +++ b/Objects/unicodeobject.c Sat Jun 18 13:56:16 2016 +0300 @@ -3837,7 +3837,7 @@ output = arg; Py_INCREF(output); } - else { + else if (PyObject_CheckBuffer(arg)) { arg = PyBytes_FromObject(arg); if (!arg) return 0; @@ -3852,6 +3852,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;