Commit bde9d6bb authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

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
parent a22df489
...@@ -3290,9 +3290,9 @@ class LocaleCodecTest(unittest.TestCase): ...@@ -3290,9 +3290,9 @@ class LocaleCodecTest(unittest.TestCase):
expected = text.encode(self.ENCODING, errors) expected = text.encode(self.ENCODING, errors)
except UnicodeEncodeError: except UnicodeEncodeError:
with self.assertRaises(RuntimeError) as cm: with self.assertRaises(RuntimeError) as cm:
self.encode(self.SURROGATES) self.encode(text, errors)
errmsg = str(cm.exception) 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: else:
encoded = self.encode(text, errors) encoded = self.encode(text, errors)
self.assertEqual(encoded, expected) self.assertEqual(encoded, expected)
...@@ -3315,6 +3315,11 @@ class LocaleCodecTest(unittest.TestCase): ...@@ -3315,6 +3315,11 @@ class LocaleCodecTest(unittest.TestCase):
self.check_encode_strings("surrogatepass") 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"): def decode(self, encoded, errors="strict"):
return _testcapi.DecodeLocaleEx(encoded, 0, errors) return _testcapi.DecodeLocaleEx(encoded, 0, errors)
...@@ -3370,6 +3375,11 @@ class LocaleCodecTest(unittest.TestCase): ...@@ -3370,6 +3375,11 @@ class LocaleCodecTest(unittest.TestCase):
self.check_decode_strings("surrogatepass") 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__": if __name__ == "__main__":
unittest.main() unittest.main()
Fix memory leak in :c:func:`PyUnicode_EncodeLocale` and
:c:func:`PyUnicode_EncodeFSDefault` on error handling.
...@@ -3449,10 +3449,9 @@ unicode_encode_locale(PyObject *unicode, const char *errors, ...@@ -3449,10 +3449,9 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
return NULL; return NULL;
} }
Py_ssize_t wlen2 = wcslen(wstr); if ((size_t)wlen != wcslen(wstr)) {
if (wlen2 != wlen) {
PyMem_Free(wstr);
PyErr_SetString(PyExc_ValueError, "embedded null character"); PyErr_SetString(PyExc_ValueError, "embedded null character");
PyMem_Free(wstr);
return NULL; return NULL;
} }
...@@ -3461,6 +3460,8 @@ unicode_encode_locale(PyObject *unicode, const char *errors, ...@@ -3461,6 +3460,8 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
const char *reason; const char *reason;
int res = _Py_EncodeLocaleEx(wstr, &str, &error_pos, &reason, int res = _Py_EncodeLocaleEx(wstr, &str, &error_pos, &reason,
current_locale, error_handler); current_locale, error_handler);
PyMem_Free(wstr);
if (res != 0) { if (res != 0) {
if (res == -2) { if (res == -2) {
PyObject *exc; PyObject *exc;
...@@ -3473,18 +3474,15 @@ unicode_encode_locale(PyObject *unicode, const char *errors, ...@@ -3473,18 +3474,15 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
PyCodec_StrictErrors(exc); PyCodec_StrictErrors(exc);
Py_DECREF(exc); Py_DECREF(exc);
} }
return NULL;
} }
else if (res == -3) { else if (res == -3) {
PyErr_SetString(PyExc_ValueError, "unsupported error handler"); PyErr_SetString(PyExc_ValueError, "unsupported error handler");
} }
else { else {
PyErr_NoMemory(); PyErr_NoMemory();
PyMem_Free(wstr);
return NULL;
} }
return NULL;
} }
PyMem_Free(wstr);
PyObject *bytes = PyBytes_FromString(str); PyObject *bytes = PyBytes_FromString(str);
PyMem_RawFree(str); PyMem_RawFree(str);
......
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