https://github.com/python/cpython/commit/73358fca05fe5440d463a0ab68b189fb1a714ba8
commit: 73358fca05fe5440d463a0ab68b189fb1a714ba8
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: JelleZijlstra <[email protected]>
date: 2026-10-20T18:25:38Z
summary:

[3.15] gh-159739: Bound encoding-name lookahead in surrogatepass (GH-159785) 
(#159911)



(cherry picked from commit 905aab60f72ec5aa9183ec0b74b5eda8f9ca188d)

Co-authored-by: Jelle Zijlstra <[email protected]>
Co-authored-by: Jelle Zijlstra <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.243aa8.rst
M Lib/test/test_codeccallbacks.py
M Python/codecs.c

diff --git a/Lib/test/test_codeccallbacks.py b/Lib/test/test_codeccallbacks.py
index 65d54d1004d647..7ab8eea0142520 100644
--- a/Lib/test/test_codeccallbacks.py
+++ b/Lib/test/test_codeccallbacks.py
@@ -755,6 +755,18 @@ def test_badandgoodsurrogatepassexceptions(self):
                     (s[:1], 1 + n)
                 )
 
+    def test_surrogatepass_truncated_encoding_name(self):
+        handler = codecs.lookup_error('surrogatepass')
+        for width in (16, 32):
+            encoding = f'utf-{width}-'
+            data = (0xd800).to_bytes(width // 8, 'little')
+            for exc in (UnicodeEncodeError(encoding, '\ud800', 0, 1, 'test'),
+                        UnicodeDecodeError(encoding, data, 0, len(data), 
'test')):
+                with self.subTest(encoding=encoding, error=type(exc).__name__):
+                    with self.assertRaises(type(exc)) as cm:
+                        handler(exc)
+                    self.assertIs(cm.exception, exc)
+
     def test_badhandlerresults(self):
         results = ( 42, "foo", (1,2,3), ("foo", 1, 3), ("foo", None), 
("foo",), ("foo", 1, 3), ("foo", None), ("foo",) )
         encs = ("ascii", "latin-1", "iso-8859-1", "iso-8859-15")
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.243aa8.rst 
b/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.243aa8.rst
new file mode 100644
index 00000000000000..a9452184e7838f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.243aa8.rst
@@ -0,0 +1,2 @@
+Avoid reading past the end of an encoding name when the ``surrogatepass``
+error handler receives a truncated UTF-16 or UTF-32 name.
diff --git a/Python/codecs.c b/Python/codecs.c
index 2cf8460d2087cf..c881d82e30307a 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -1172,7 +1172,8 @@ get_standard_encoding_impl(const char *encoding, int 
*bytelength)
             }
             if (*encoding == '-' || *encoding == '_' )
                 encoding++;
-            if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
+            if (encoding[0] != '\0' &&
+                Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
                 if (Py_TOLOWER(encoding[0]) == 'b')
                     return ENC_UTF16BE;
                 if (Py_TOLOWER(encoding[0]) == 'l')
@@ -1191,7 +1192,8 @@ get_standard_encoding_impl(const char *encoding, int 
*bytelength)
             }
             if (*encoding == '-' || *encoding == '_' )
                 encoding++;
-            if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
+            if (encoding[0] != '\0' &&
+                Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
                 if (Py_TOLOWER(encoding[0]) == 'b')
                     return ENC_UTF32BE;
                 if (Py_TOLOWER(encoding[0]) == 'l')

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to