mirror of https://github.com/python/cpython
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:
commit
7ab4af0427
|
@ -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);
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue