Skip to content

Commit 442d6ad

Browse files
miss-islingtonjelle-openaiJelleZijlstra
authored
[3.14] gh-159739: Bound encoding-name lookahead in surrogatepass (GH-159785) (#159912)
(cherry picked from commit 905aab6) Co-authored-by: Jelle Zijlstra <jelle@openai.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent 28cb41d commit 442d6ad

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

‎Lib/test/test_codeccallbacks.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,18 @@ def test_badandgoodsurrogatepassexceptions(self):
756756
(s[:1], 1 + n)
757757
)
758758

759+
def test_surrogatepass_truncated_encoding_name(self):
760+
handler = codecs.lookup_error('surrogatepass')
761+
for width in (16, 32):
762+
encoding = f'utf-{width}-'
763+
data = (0xd800).to_bytes(width // 8, 'little')
764+
for exc in (UnicodeEncodeError(encoding, '\ud800', 0, 1, 'test'),
765+
UnicodeDecodeError(encoding, data, 0, len(data), 'test')):
766+
with self.subTest(encoding=encoding, error=type(exc).__name__):
767+
with self.assertRaises(type(exc)) as cm:
768+
handler(exc)
769+
self.assertIs(cm.exception, exc)
770+
759771
def test_badhandlerresults(self):
760772
results = ( 42, "foo", (1,2,3), ("foo", 1, 3), ("foo", None), ("foo",), ("foo", 1, 3), ("foo", None), ("foo",) )
761773
encs = ("ascii", "latin-1", "iso-8859-1", "iso-8859-15")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid reading past the end of an encoding name when the ``surrogatepass``
2+
error handler receives a truncated UTF-16 or UTF-32 name.

‎Python/codecs.c‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,8 @@ get_standard_encoding_impl(const char *encoding, int *bytelength)
11781178
}
11791179
if (*encoding == '-' || *encoding == '_' )
11801180
encoding++;
1181-
if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
1181+
if (encoding[0] != '\0' &&
1182+
Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
11821183
if (Py_TOLOWER(encoding[0]) == 'b')
11831184
return ENC_UTF16BE;
11841185
if (Py_TOLOWER(encoding[0]) == 'l')
@@ -1197,7 +1198,8 @@ get_standard_encoding_impl(const char *encoding, int *bytelength)
11971198
}
11981199
if (*encoding == '-' || *encoding == '_' )
11991200
encoding++;
1200-
if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
1201+
if (encoding[0] != '\0' &&
1202+
Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
12011203
if (Py_TOLOWER(encoding[0]) == 'b')
12021204
return ENC_UTF32BE;
12031205
if (Py_TOLOWER(encoding[0]) == 'l')

0 commit comments

Comments
 (0)