Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as

an iterable of integers. Now only strings and byte-like objects are accepted.
This commit is contained in:
Serhiy Storchaka 2016-06-18 13:56:16 +03:00
commit f95de0e8cc
6 changed files with 61 additions and 1 deletions

View File

@ -472,6 +472,13 @@ if 1:
d = {f(): f(), f(): f()} d = {f(): f(), f(): f()}
self.assertEqual(d, {1: 2, 3: 4}) 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 @support.cpython_only
def test_same_filename_used(self): def test_same_filename_used(self):
s = """def f(): pass\ndef g(): pass""" s = """def f(): pass\ndef g(): pass"""

View File

@ -626,6 +626,22 @@ class CompileTestCase(unittest.TestCase):
code2 = parser.compilest(st) code2 = parser.compilest(st)
self.assertEqual(eval(code2), -3) 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): class ParserStackLimitTestCase(unittest.TestCase):
"""try to push the parser to/over its limits. """try to push the parser to/over its limits.
see http://bugs.python.org/issue1881 for a discussion see http://bugs.python.org/issue1881 for a discussion

View File

@ -157,6 +157,12 @@ class SymtableTest(unittest.TestCase):
self.fail("no SyntaxError for %r" % (brokencode,)) self.fail("no SyntaxError for %r" % (brokencode,))
checkfilename("def f(x): foo)(") # parse-time checkfilename("def f(x): foo)(") # parse-time
checkfilename("def f(x): global x") # symtable-build-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): def test_eval(self):
symbols = symtable.symtable("42", "?", "eval") symbols = symtable.symtable("42", "?", "eval")

View File

@ -619,6 +619,19 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
finally: finally:
os.remove(filename) 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 @support.requires_zlib
class CompressedZipImportTestCase(UncompressedZipImportTestCase): class CompressedZipImportTestCase(UncompressedZipImportTestCase):
@ -639,6 +652,8 @@ class BadFileZipImportTestCase(unittest.TestCase):
def testBadArgs(self): def testBadArgs(self):
self.assertRaises(TypeError, zipimport.zipimporter, None) self.assertRaises(TypeError, zipimport.zipimporter, None)
self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None) self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None)
self.assertRaises(TypeError, zipimport.zipimporter,
list(os.fsencode(TESTMOD)))
def testFilenameTooLong(self): def testFilenameTooLong(self):
self.assertZipFailure('A' * 33000) self.assertZipFailure('A' * 33000)

View File

@ -10,6 +10,10 @@ What's New in Python 3.6.0 alpha 3
Library 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 - Issue #26536: socket.ioctl now supports SIO_LOOPBACK_FAST_PATH. Patch by
Daniel Stokes. Daniel Stokes.
@ -52,6 +56,12 @@ IDLE
- Issue #27310: Fix IDLE.app failure to launch on OS X due to vestigial import. - 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 Build
----- -----

View File

@ -3837,7 +3837,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
output = arg; output = arg;
Py_INCREF(output); Py_INCREF(output);
} }
else { else if (PyObject_CheckBuffer(arg)) {
arg = PyBytes_FromObject(arg); arg = PyBytes_FromObject(arg);
if (!arg) if (!arg)
return 0; return 0;
@ -3852,6 +3852,12 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
return 0; 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) { if (PyUnicode_READY(output) == -1) {
Py_DECREF(output); Py_DECREF(output);
return 0; return 0;