diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-11-28 09:26:20 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-28 09:26:20 (GMT) |
commit | bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6 (patch) | |
tree | ef525570f785225ab3da54b867b2ea4cb137fb40 | |
parent | a22df4896f6b83c8741203118790ae281716bca5 (diff) | |
download | cpython-bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6.zip cpython-bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6.tar.gz cpython-bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6.tar.bz2 |
bpo-34523, bpo-35322: Fix unicode_encode_locale() (GH-10759)
Fix memory leak in PyUnicode_EncodeLocale() and
PyUnicode_EncodeFSDefault() on error handling.
Changes:
* Fix unicode_encode_locale() error handling
* Fix test_codecs.LocaleCodecTest
-rw-r--r-- | Lib/test/test_codecs.py | 14 | ||||
-rw-r--r-- | Misc/NEWS.d/next/C API/2018-11-28-03-20-36.bpo-35322.Qcqsag.rst | 2 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 12 |
3 files changed, 19 insertions, 9 deletions
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 00b5d31..8c92556 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -3290,9 +3290,9 @@ class LocaleCodecTest(unittest.TestCase): expected = text.encode(self.ENCODING, errors) except UnicodeEncodeError: with self.assertRaises(RuntimeError) as cm: - self.encode(self.SURROGATES) + self.encode(text, errors) errmsg = str(cm.exception) - self.assertTrue(errmsg.startswith("encode error: pos=0, reason="), errmsg) + self.assertRegex(errmsg, r"encode error: pos=[0-9]+, reason=") else: encoded = self.encode(text, errors) self.assertEqual(encoded, expected) @@ -3315,6 +3315,11 @@ class LocaleCodecTest(unittest.TestCase): self.check_encode_strings("surrogatepass") + def test_encode_unsupported_error_handler(self): + with self.assertRaises(ValueError) as cm: + self.encode('', 'backslashreplace') + self.assertEqual(str(cm.exception), 'unsupported error handler') + def decode(self, encoded, errors="strict"): return _testcapi.DecodeLocaleEx(encoded, 0, errors) @@ -3370,6 +3375,11 @@ class LocaleCodecTest(unittest.TestCase): self.check_decode_strings("surrogatepass") + def test_decode_unsupported_error_handler(self): + with self.assertRaises(ValueError) as cm: + self.decode(b'', 'backslashreplace') + self.assertEqual(str(cm.exception), 'unsupported error handler') + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/C API/2018-11-28-03-20-36.bpo-35322.Qcqsag.rst b/Misc/NEWS.d/next/C API/2018-11-28-03-20-36.bpo-35322.Qcqsag.rst new file mode 100644 index 0000000..f5b4796 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2018-11-28-03-20-36.bpo-35322.Qcqsag.rst @@ -0,0 +1,2 @@ +Fix memory leak in :c:func:`PyUnicode_EncodeLocale` and +:c:func:`PyUnicode_EncodeFSDefault` on error handling. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 2b1db91..bc98c44 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3449,10 +3449,9 @@ unicode_encode_locale(PyObject *unicode, const char *errors, return NULL; } - Py_ssize_t wlen2 = wcslen(wstr); - if (wlen2 != wlen) { - PyMem_Free(wstr); + if ((size_t)wlen != wcslen(wstr)) { PyErr_SetString(PyExc_ValueError, "embedded null character"); + PyMem_Free(wstr); return NULL; } @@ -3461,6 +3460,8 @@ unicode_encode_locale(PyObject *unicode, const char *errors, const char *reason; int res = _Py_EncodeLocaleEx(wstr, &str, &error_pos, &reason, current_locale, error_handler); + PyMem_Free(wstr); + if (res != 0) { if (res == -2) { PyObject *exc; @@ -3473,18 +3474,15 @@ unicode_encode_locale(PyObject *unicode, const char *errors, PyCodec_StrictErrors(exc); Py_DECREF(exc); } - return NULL; } else if (res == -3) { PyErr_SetString(PyExc_ValueError, "unsupported error handler"); } else { PyErr_NoMemory(); - PyMem_Free(wstr); - return NULL; } + return NULL; } - PyMem_Free(wstr); PyObject *bytes = PyBytes_FromString(str); PyMem_RawFree(str); |