Commit 1334884f authored by Antoine Pitrou's avatar Antoine Pitrou

Issue #13848: open() and the FileIO constructor now check for NUL characters in the file name.

Patch by Hynek Schlawack.
parent c875d203
...@@ -1501,6 +1501,12 @@ PyAPI_FUNC(int) PyUnicode_Contains( ...@@ -1501,6 +1501,12 @@ PyAPI_FUNC(int) PyUnicode_Contains(
PyObject *element /* Element string */ PyObject *element /* Element string */
); );
/* Checks whether the string contains any NUL characters. */
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyUnicode_HasNULChars(PyObject *);
#endif
/* Checks whether argument is a valid identifier. */ /* Checks whether argument is a valid identifier. */
PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s); PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s);
......
...@@ -305,6 +305,11 @@ class OtherFileTests(unittest.TestCase): ...@@ -305,6 +305,11 @@ class OtherFileTests(unittest.TestCase):
finally: finally:
os.unlink(TESTFN) os.unlink(TESTFN)
def testConstructorHandlesNULChars(self):
fn_with_NUL = 'foo\0bar'
self.assertRaises(TypeError, _FileIO, fn_with_NUL, 'w')
self.assertRaises(TypeError, _FileIO, bytes(fn_with_NUL, 'ascii'), 'w')
def testInvalidFd(self): def testInvalidFd(self):
self.assertRaises(ValueError, _FileIO, -10) self.assertRaises(ValueError, _FileIO, -10)
self.assertRaises(OSError, _FileIO, make_bad_fd()) self.assertRaises(OSError, _FileIO, make_bad_fd())
......
...@@ -363,6 +363,11 @@ class IOTest(unittest.TestCase): ...@@ -363,6 +363,11 @@ class IOTest(unittest.TestCase):
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR) self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
self.assertRaises(exc, fp.seek, -1, self.SEEK_END) self.assertRaises(exc, fp.seek, -1, self.SEEK_END)
def test_open_handles_NUL_chars(self):
fn_with_NUL = 'foo\0bar'
self.assertRaises(TypeError, self.open, fn_with_NUL, 'w')
self.assertRaises(TypeError, self.open, bytes(fn_with_NUL, 'ascii'), 'w')
def test_raw_file_io(self): def test_raw_file_io(self):
with self.open(support.TESTFN, "wb", buffering=0) as f: with self.open(support.TESTFN, "wb", buffering=0) as f:
self.assertEqual(f.readable(), False) self.assertEqual(f.readable(), False)
......
...@@ -811,6 +811,7 @@ Michael Scharf ...@@ -811,6 +811,7 @@ Michael Scharf
Andreas Schawo Andreas Schawo
Neil Schemenauer Neil Schemenauer
David Scherer David Scherer
Hynek Schlawack
Bob Schmertz Bob Schmertz
Gregor Schmid Gregor Schmid
Ralf Schmitt Ralf Schmitt
......
...@@ -111,6 +111,9 @@ Core and Builtins ...@@ -111,6 +111,9 @@ Core and Builtins
Library Library
------- -------
- Issue #13848: open() and the FileIO constructor now check for NUL
characters in the file name. Patch by Hynek Schlawack.
- Issue #13806: The size check in audioop decompression functions was too - Issue #13806: The size check in audioop decompression functions was too
strict and could reject valid compressed data. Patch by Oleg Plakhotnyuk. strict and could reject valid compressed data. Patch by Oleg Plakhotnyuk.
......
...@@ -253,35 +253,24 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) ...@@ -253,35 +253,24 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
} }
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (PyUnicode_Check(nameobj)) if (PyUnicode_Check(nameobj)) {
int rv = _PyUnicode_HasNULChars(nameobj);
if (rv) {
if (rv != -1)
PyErr_SetString(PyExc_TypeError, "embedded NUL character");
return -1;
}
widename = PyUnicode_AS_UNICODE(nameobj); widename = PyUnicode_AS_UNICODE(nameobj);
}
if (widename == NULL) if (widename == NULL)
#endif #endif
if (fd < 0) if (fd < 0)
{ {
if (PyBytes_Check(nameobj) || PyByteArray_Check(nameobj)) { if (!PyUnicode_FSConverter(nameobj, &stringobj)) {
Py_ssize_t namelen;
if (PyObject_AsCharBuffer(nameobj, &name, &namelen) < 0)
return -1;
}
else {
PyObject *u = PyUnicode_FromObject(nameobj);
if (u == NULL)
return -1;
stringobj = PyUnicode_EncodeFSDefault(u);
Py_DECREF(u);
if (stringobj == NULL)
return -1; return -1;
if (!PyBytes_Check(stringobj)) {
PyErr_SetString(PyExc_TypeError,
"encoder failed to return bytes");
goto error;
} }
name = PyBytes_AS_STRING(stringobj); name = PyBytes_AS_STRING(stringobj);
} }
}
s = mode; s = mode;
while (*s) { while (*s) {
......
...@@ -1866,6 +1866,19 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) ...@@ -1866,6 +1866,19 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
} }
int
_PyUnicode_HasNULChars(PyObject* s)
{
static PyObject *nul = NULL;
if (nul == NULL)
nul = PyUnicode_FromStringAndSize("\0", 1);
if (nul == NULL)
return -1;
return PyUnicode_Contains(s, nul);
}
int int
PyUnicode_FSConverter(PyObject* arg, void* addr) PyUnicode_FSConverter(PyObject* arg, void* addr)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment