mirror of https://github.com/python/cpython
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
This commit is contained in:
parent
a22df4896f
commit
bde9d6bbb4
|
@ -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):
|
||||||
|
|
||||||
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):
|
||||||
|
|
||||||
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()
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
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,
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue