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

Patch by Hynek Schlawack.
This commit is contained in:
Antoine Pitrou 2012-01-29 18:43:36 +01:00
commit 7ab4af0427
6 changed files with 41 additions and 21 deletions

View File

@ -1914,6 +1914,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);

View File

@ -306,6 +306,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())

View File

@ -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)

View File

@ -461,6 +461,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.

View File

@ -258,6 +258,12 @@ 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_AsUnicode(nameobj); widename = PyUnicode_AsUnicode(nameobj);
if (widename == NULL) if (widename == NULL)
return -1; return -1;
@ -265,29 +271,11 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
#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; 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;
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) {

View File

@ -3574,6 +3574,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)
{ {