From d8a1447c9980be5f1d8ae806f7aecd814b1cd6f6 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 6 Sep 2014 20:07:17 +0300 Subject: [PATCH] Issue #22215: Now ValueError is raised instead of TypeError when str or bytes argument contains not permitted null character or byte. --- Lib/test/test_builtin.py | 4 ++-- Lib/test/test_fileio.py | 4 ++-- Lib/test/test_getargs2.py | 10 +++++----- Lib/test/test_io.py | 4 ++-- Lib/test/test_site.py | 2 +- Misc/NEWS | 3 +++ Modules/_io/fileio.c | 2 +- Modules/_tkinter.c | 4 ++-- Modules/posixmodule.c | 2 +- Modules/socketmodule.c | 2 +- Objects/bytesobject.c | 4 ++-- Objects/unicodeobject.c | 10 +++++----- Python/bltinmodule.c | 4 ++-- Python/getargs.c | 25 ++++++++++++------------- 14 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 018ac8d9213..c78fce090a8 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -312,11 +312,11 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(TypeError, compile) self.assertRaises(ValueError, compile, 'print(42)\n', '', 'badmode') self.assertRaises(ValueError, compile, 'print(42)\n', '', 'single', 0xff) - self.assertRaises(TypeError, compile, chr(0), 'f', 'exec') + self.assertRaises(ValueError, compile, chr(0), 'f', 'exec') self.assertRaises(TypeError, compile, 'pass', '?', 'exec', mode='eval', source='0', filename='tmp') compile('print("\xe5")\n', '', 'exec') - self.assertRaises(TypeError, compile, chr(0), 'f', 'exec') + self.assertRaises(ValueError, compile, chr(0), 'f', 'exec') self.assertRaises(ValueError, compile, str('a = 1'), 'f', 'bad') # test the optimize argument diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index b87dc07805a..41be95e04f9 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -361,8 +361,8 @@ class OtherFileTests(unittest.TestCase): 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') + self.assertRaises(ValueError, _FileIO, fn_with_NUL, 'w') + self.assertRaises(ValueError, _FileIO, bytes(fn_with_NUL, 'ascii'), 'w') def testInvalidFd(self): self.assertRaises(ValueError, _FileIO, -10) diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py index 1853a2dbed7..cf1279dc68b 100644 --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -482,7 +482,7 @@ class Bytes_TestCase(unittest.TestCase): def test_s(self): from _testcapi import getargs_s self.assertEqual(getargs_s('abc\xe9'), b'abc\xc3\xa9') - self.assertRaises(TypeError, getargs_s, 'nul:\0') + self.assertRaises(ValueError, getargs_s, 'nul:\0') self.assertRaises(TypeError, getargs_s, b'bytes') self.assertRaises(TypeError, getargs_s, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_s, memoryview(b'memoryview')) @@ -509,7 +509,7 @@ class Bytes_TestCase(unittest.TestCase): def test_z(self): from _testcapi import getargs_z self.assertEqual(getargs_z('abc\xe9'), b'abc\xc3\xa9') - self.assertRaises(TypeError, getargs_z, 'nul:\0') + self.assertRaises(ValueError, getargs_z, 'nul:\0') self.assertRaises(TypeError, getargs_z, b'bytes') self.assertRaises(TypeError, getargs_z, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_z, memoryview(b'memoryview')) @@ -537,7 +537,7 @@ class Bytes_TestCase(unittest.TestCase): from _testcapi import getargs_y self.assertRaises(TypeError, getargs_y, 'abc\xe9') self.assertEqual(getargs_y(b'bytes'), b'bytes') - self.assertRaises(TypeError, getargs_y, b'nul:\0') + self.assertRaises(ValueError, getargs_y, b'nul:\0') self.assertRaises(TypeError, getargs_y, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_y, memoryview(b'memoryview')) self.assertRaises(TypeError, getargs_y, None) @@ -577,7 +577,7 @@ class Unicode_TestCase(unittest.TestCase): def test_u(self): from _testcapi import getargs_u self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9') - self.assertRaises(TypeError, getargs_u, 'nul:\0') + self.assertRaises(ValueError, getargs_u, 'nul:\0') self.assertRaises(TypeError, getargs_u, b'bytes') self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview')) @@ -595,7 +595,7 @@ class Unicode_TestCase(unittest.TestCase): def test_Z(self): from _testcapi import getargs_Z self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9') - self.assertRaises(TypeError, getargs_Z, 'nul:\0') + self.assertRaises(ValueError, getargs_Z, 'nul:\0') self.assertRaises(TypeError, getargs_Z, b'bytes') self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray')) self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview')) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index 935e7c9dbbd..e499ba2cdac 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -363,8 +363,8 @@ class IOTest(unittest.TestCase): 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') + self.assertRaises(ValueError, self.open, fn_with_NUL, 'w') + self.assertRaises(ValueError, self.open, bytes(fn_with_NUL, 'ascii'), 'w') def test_raw_file_io(self): with self.open(support.TESTFN, "wb", buffering=0) as f: diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index c2f37f85663..79af49cb092 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -147,7 +147,7 @@ class HelperFunctionsTests(unittest.TestCase): re.escape(os.path.join(pth_dir, pth_fn))) # XXX: ditto previous XXX comment. self.assertRegex(err_out.getvalue(), 'Traceback') - self.assertRegex(err_out.getvalue(), 'TypeError') + self.assertRegex(err_out.getvalue(), 'ValueError') def test_addsitedir(self): # Same tests for test_addpackage since addsitedir() essentially just diff --git a/Misc/NEWS b/Misc/NEWS index 22017083c1f..eb758524933 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: TBA Core and Builtins ----------------- +- Issue #22215: Now ValueError is raised instead of TypeError when str or bytes + argument contains not permitted null character or byte. + - Issue #22258: Fix the internal function set_inheritable() on Illumos. This platform exposes the function ``ioctl(FIOCLEX)``, but calling it fails with errno is ENOTTY: "Inappropriate ioctl for device". set_inheritable() diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 280523bc2b3..84d2ff35b0d 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -256,7 +256,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) int rv = _PyUnicode_HasNULChars(nameobj); if (rv) { if (rv != -1) - PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + PyErr_SetString(PyExc_ValueError, "embedded null character"); return -1; } widename = PyUnicode_AsUnicode(nameobj); diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 4df45ad600c..d54ebb47a35 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1417,7 +1417,7 @@ varname_converter(PyObject *in, void *_out) } s = PyBytes_AsString(in); if (strlen(s) != (size_t)PyBytes_Size(in)) { - PyErr_SetString(PyExc_ValueError, "null byte in bytes object"); + PyErr_SetString(PyExc_ValueError, "embedded null byte"); return 0; } *out = s; @@ -1434,7 +1434,7 @@ varname_converter(PyObject *in, void *_out) return 0; } if (strlen(s) != (size_t)size) { - PyErr_SetString(PyExc_ValueError, "null character in string"); + PyErr_SetString(PyExc_ValueError, "embedded null character"); return 0; } *out = s; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index af5c2a691fd..473fefaa344 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -903,7 +903,7 @@ path_converter(PyObject *o, void *p) { narrow = PyBytes_AS_STRING(bytes); if ((size_t)length != strlen(narrow)) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded NUL character in %s"); + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); Py_DECREF(bytes); return 0; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index db69d6e4681..7738c30c418 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1273,7 +1273,7 @@ idna_converter(PyObject *obj, struct maybe_idna *data) } if (strlen(data->buf) != len) { Py_CLEAR(data->obj); - PyErr_SetString(PyExc_TypeError, "host name must not contain NUL character"); + PyErr_SetString(PyExc_TypeError, "host name must not contain null character"); return 0; } return Py_CLEANUP_SUPPORTED; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index f0c26c33e50..63d5a5c6c3c 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -593,8 +593,8 @@ PyBytes_AsStringAndSize(PyObject *obj, if (len != NULL) *len = PyBytes_GET_SIZE(obj); else if (strlen(*s) != (size_t)PyBytes_GET_SIZE(obj)) { - PyErr_SetString(PyExc_TypeError, - "expected bytes with no null"); + PyErr_SetString(PyExc_ValueError, + "embedded null byte"); return -1; } return 0; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index e7ff126630d..f5d7b78ba1a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3247,7 +3247,7 @@ PyUnicode_EncodeLocale(PyObject *unicode, const char *errors) wlen2 = wcslen(wstr); if (wlen2 != wlen) { PyMem_Free(wstr); - PyErr_SetString(PyExc_TypeError, "embedded null character"); + PyErr_SetString(PyExc_ValueError, "embedded null character"); return NULL; } @@ -3519,8 +3519,8 @@ PyUnicode_DecodeLocaleAndSize(const char *str, Py_ssize_t len, if (locale_error_handler(errors, &surrogateescape) < 0) return NULL; - if (str[len] != '\0' || (size_t)len != strlen(str)) { - PyErr_SetString(PyExc_TypeError, "embedded null character"); + if (str[len] != '\0' || (size_t)len != strlen(str)) { + PyErr_SetString(PyExc_ValueError, "embedded null byte"); return NULL; } @@ -3697,7 +3697,7 @@ PyUnicode_FSConverter(PyObject* arg, void* addr) size = PyBytes_GET_SIZE(output); data = PyBytes_AS_STRING(output); if ((size_t)size != strlen(data)) { - PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + PyErr_SetString(PyExc_ValueError, "embedded null byte"); Py_DECREF(output); return 0; } @@ -3741,7 +3741,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr) } if (findchar(PyUnicode_DATA(output), PyUnicode_KIND(output), PyUnicode_GET_LENGTH(output), 0, 1) >= 0) { - PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + PyErr_SetString(PyExc_ValueError, "embedded null character"); Py_DECREF(output); return 0; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index cbadc122182..068398fb9b8 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -745,8 +745,8 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) return NULL; } - if (strlen(str) != (size_t)size) { - PyErr_SetString(PyExc_TypeError, + if (strlen(str) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "source code string cannot contain null bytes"); return NULL; } diff --git a/Python/getargs.c b/Python/getargs.c index a3132696586..c749bb643cb 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -872,10 +872,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, STORE_SIZE(count); format++; } else { - if (strlen(*p) != (size_t)count) - return converterr( - "bytes without null bytes", - arg, msgbuf, bufsize); + if (strlen(*p) != (size_t)count) { + PyErr_SetString(PyExc_ValueError, "embedded null byte"); + RETURN_ERR_OCCURRED; + } } break; } @@ -948,16 +948,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (sarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); + if (strlen(sarg) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + RETURN_ERR_OCCURRED; + } *p = sarg; } else return converterr(c == 'z' ? "str or None" : "str", arg, msgbuf, bufsize); - if (*p != NULL && sarg != NULL && (Py_ssize_t) strlen(*p) != len) - return converterr( - c == 'z' ? "str without null characters or None" - : "str without null characters", - arg, msgbuf, bufsize); } break; } @@ -994,10 +993,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = PyUnicode_AsUnicodeAndSize(arg, &len); if (*p == NULL) RETURN_ERR_OCCURRED; - if (Py_UNICODE_strlen(*p) != (size_t)len) - return converterr( - "str without null characters or None", - arg, msgbuf, bufsize); + if (Py_UNICODE_strlen(*p) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + RETURN_ERR_OCCURRED; + } } else return converterr(c == 'Z' ? "str or None" : "str", arg, msgbuf, bufsize);