Skip to content

Commit bde9d6b

Browse files
authored
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
1 parent a22df48 commit bde9d6b

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

Lib/test/test_codecs.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,9 +3290,9 @@ def check_encode_strings(self, errors):
32903290
expected = text.encode(self.ENCODING, errors)
32913291
except UnicodeEncodeError:
32923292
with self.assertRaises(RuntimeError) as cm:
3293-
self.encode(self.SURROGATES)
3293+
self.encode(text, errors)
32943294
errmsg = str(cm.exception)
3295-
self.assertTrue(errmsg.startswith("encode error: pos=0, reason="), errmsg)
3295+
self.assertRegex(errmsg, r"encode error: pos=[0-9]+, reason=")
32963296
else:
32973297
encoded = self.encode(text, errors)
32983298
self.assertEqual(encoded, expected)
@@ -3315,6 +3315,11 @@ def test_encode_surrogatepass(self):
33153315

33163316
self.check_encode_strings("surrogatepass")
33173317

3318+
def test_encode_unsupported_error_handler(self):
3319+
with self.assertRaises(ValueError) as cm:
3320+
self.encode('', 'backslashreplace')
3321+
self.assertEqual(str(cm.exception), 'unsupported error handler')
3322+
33183323
def decode(self, encoded, errors="strict"):
33193324
return _testcapi.DecodeLocaleEx(encoded, 0, errors)
33203325

@@ -3370,6 +3375,11 @@ def test_decode_surrogatepass(self):
33703375

33713376
self.check_decode_strings("surrogatepass")
33723377

3378+
def test_decode_unsupported_error_handler(self):
3379+
with self.assertRaises(ValueError) as cm:
3380+
self.decode(b'', 'backslashreplace')
3381+
self.assertEqual(str(cm.exception), 'unsupported error handler')
3382+
33733383

33743384
if __name__ == "__main__":
33753385
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix memory leak in :c:func:`PyUnicode_EncodeLocale` and
2+
:c:func:`PyUnicode_EncodeFSDefault` on error handling.

Objects/unicodeobject.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3449,10 +3449,9 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
34493449
return NULL;
34503450
}
34513451

3452-
Py_ssize_t wlen2 = wcslen(wstr);
3453-
if (wlen2 != wlen) {
3454-
PyMem_Free(wstr);
3452+
if ((size_t)wlen != wcslen(wstr)) {
34553453
PyErr_SetString(PyExc_ValueError, "embedded null character");
3454+
PyMem_Free(wstr);
34563455
return NULL;
34573456
}
34583457

@@ -3461,6 +3460,8 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
34613460
const char *reason;
34623461
int res = _Py_EncodeLocaleEx(wstr, &str, &error_pos, &reason,
34633462
current_locale, error_handler);
3463+
PyMem_Free(wstr);
3464+
34643465
if (res != 0) {
34653466
if (res == -2) {
34663467
PyObject *exc;
@@ -3473,18 +3474,15 @@ unicode_encode_locale(PyObject *unicode, const char *errors,
34733474
PyCodec_StrictErrors(exc);
34743475
Py_DECREF(exc);
34753476
}
3476-
return NULL;
34773477
}
34783478
else if (res == -3) {
34793479
PyErr_SetString(PyExc_ValueError, "unsupported error handler");
34803480
}
34813481
else {
34823482
PyErr_NoMemory();
3483-
PyMem_Free(wstr);
3484-
return NULL;
34853483
}
3484+
return NULL;
34863485
}
3487-
PyMem_Free(wstr);
34883486

34893487
PyObject *bytes = PyBytes_FromString(str);
34903488
PyMem_RawFree(str);

0 commit comments

Comments
 (0)