https://github.com/python/cpython/commit/ea784fa9ac46ee9e688fe19138db1b9be13b3f35
commit: ea784fa9ac46ee9e688fe19138db1b9be13b3f35
branch: main
author: Gregory P. Smith <[email protected]>
committer: gpshead <[email protected]>
date: 2026-11-01T10:24:37-08:00
summary:

gh-161090: Reject a leading delimiter in the punycode decoder (GH-161091)

RFC 3492 section 6.2 only consumes the delimiter when at least one basic
code point precedes it.  A leading "-" is now an invalid digit.

ANT-2026-0IEDOPPK

files:
A Misc/NEWS.d/next/Library/2026-10-22-05-19-56.gh-issue-161090.pxZ1IA.rst
M Lib/encodings/punycode.py
M Lib/test/test_codecs.py

diff --git a/Lib/encodings/punycode.py b/Lib/encodings/punycode.py
index 279245f435e179..1da012229837f0 100644
--- a/Lib/encodings/punycode.py
+++ b/Lib/encodings/punycode.py
@@ -190,7 +190,10 @@ def punycode_decode(text, errors):
         text = text.encode("ascii")
     if isinstance(text, memoryview):
         text = bytes(text)
-    pos = text.rfind(b"-")
+    # RFC 3492, section 6.2: the delimiter is only consumed if at least one
+    # basic code point precedes it.  A leading "-" is left in the extended
+    # part, where it is an invalid digit.
+    pos = text.rfind(b"-", 1)
     if pos == -1:
         base = ""
         extended = text.upper()
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index 3e174fb0130c26..f26a65bb67acb1 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -1390,7 +1390,11 @@ def test_decode_invalid(self):
             (b"Proprostnemluvesky-&uyb24dma41a", "strict", 
UnicodeDecodeError("punycode", b"", 19, 20, "")),
             (b"Proprostnemluvesky-uyb24d&ma41a", "strict", 
UnicodeDecodeError("punycode", b"", 25, 26, "")),
             (b"Proprostnemluvesky-uyb24dma41a&", "strict", 
UnicodeDecodeError("punycode", b"", 30, 31, "")),
+            # A delimiter not preceded by any basic code point (RFC 3492, 6.2)
+            (b"-", "strict", UnicodeDecodeError("punycode", b"", 0, 1, "")),
+            (b"-80a1acny", "strict", UnicodeDecodeError("punycode", b"", 0, 1, 
"")),
             (b"xn--w&", "ignore", "xn-"),
+            (b"-80a1acny", "ignore", ""),
         ]
         for puny, errors, expected in testcases:
             with self.subTest(puny=puny, errors=errors):
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-22-05-19-56.gh-issue-161090.pxZ1IA.rst 
b/Misc/NEWS.d/next/Library/2026-10-22-05-19-56.gh-issue-161090.pxZ1IA.rst
new file mode 100644
index 00000000000000..40b506b39cc433
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-22-05-19-56.gh-issue-161090.pxZ1IA.rst
@@ -0,0 +1,3 @@
+Fix the ``punycode`` codec accepting a delimiter (``-``) that is not preceded
+by any basic code point. Such input, for example ``b'-80a1acny'``, now raises
+:exc:`UnicodeDecodeError`, as required by :rfc:`3492`.

_______________________________________________
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