Blame SOURCES/00394-cve-2022-45061-cpu-denial-of-service-via-inefficient-idna-decoder.patch

653c23
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
653c23
From: "Miss Islington (bot)"
653c23
 <31488909+miss-islington@users.noreply.github.com>
653c23
Date: Mon, 7 Nov 2022 19:22:14 -0800
653c23
Subject: [PATCH] 00394: CVE-2022-45061: CPU denial of service via inefficient
653c23
 IDNA decoder
653c23
653c23
gh-98433: Fix quadratic time idna decoding.
653c23
653c23
There was an unnecessary quadratic loop in idna decoding. This restores
653c23
the behavior to linear.
653c23
653c23
(cherry picked from commit a6f6c3a3d6f2b580f2d87885c9b8a9350ad7bf15)
653c23
653c23
Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
653c23
Co-authored-by: Gregory P. Smith <greg@krypto.org>
653c23
---
653c23
 Lib/encodings/idna.py                         | 32 +++++++++----------
653c23
 Lib/test/test_codecs.py                       |  6 ++++
653c23
 ...2-11-04-09-29-36.gh-issue-98433.l76c5G.rst |  6 ++++
653c23
 3 files changed, 27 insertions(+), 17 deletions(-)
653c23
 create mode 100644 Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
653c23
653c23
diff --git a/Lib/encodings/idna.py b/Lib/encodings/idna.py
653c23
index ea4058512f..bf98f51336 100644
653c23
--- a/Lib/encodings/idna.py
653c23
+++ b/Lib/encodings/idna.py
653c23
@@ -39,23 +39,21 @@ def nameprep(label):
653c23
 
653c23
     # Check bidi
653c23
     RandAL = [stringprep.in_table_d1(x) for x in label]
653c23
-    for c in RandAL:
653c23
-        if c:
653c23
-            # There is a RandAL char in the string. Must perform further
653c23
-            # tests:
653c23
-            # 1) The characters in section 5.8 MUST be prohibited.
653c23
-            # This is table C.8, which was already checked
653c23
-            # 2) If a string contains any RandALCat character, the string
653c23
-            # MUST NOT contain any LCat character.
653c23
-            if any(stringprep.in_table_d2(x) for x in label):
653c23
-                raise UnicodeError("Violation of BIDI requirement 2")
653c23
-
653c23
-            # 3) If a string contains any RandALCat character, a
653c23
-            # RandALCat character MUST be the first character of the
653c23
-            # string, and a RandALCat character MUST be the last
653c23
-            # character of the string.
653c23
-            if not RandAL[0] or not RandAL[-1]:
653c23
-                raise UnicodeError("Violation of BIDI requirement 3")
653c23
+    if any(RandAL):
653c23
+        # There is a RandAL char in the string. Must perform further
653c23
+        # tests:
653c23
+        # 1) The characters in section 5.8 MUST be prohibited.
653c23
+        # This is table C.8, which was already checked
653c23
+        # 2) If a string contains any RandALCat character, the string
653c23
+        # MUST NOT contain any LCat character.
653c23
+        if any(stringprep.in_table_d2(x) for x in label):
653c23
+            raise UnicodeError("Violation of BIDI requirement 2")
653c23
+        # 3) If a string contains any RandALCat character, a
653c23
+        # RandALCat character MUST be the first character of the
653c23
+        # string, and a RandALCat character MUST be the last
653c23
+        # character of the string.
653c23
+        if not RandAL[0] or not RandAL[-1]:
653c23
+            raise UnicodeError("Violation of BIDI requirement 3")
653c23
 
653c23
     return label
653c23
 
653c23
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
653c23
index 56485de3f6..a798d1f287 100644
653c23
--- a/Lib/test/test_codecs.py
653c23
+++ b/Lib/test/test_codecs.py
653c23
@@ -1640,6 +1640,12 @@ class IDNACodecTest(unittest.TestCase):
653c23
         self.assertEqual("pyth\xf6n.org".encode("idna"), b"xn--pythn-mua.org")
653c23
         self.assertEqual("pyth\xf6n.org.".encode("idna"), b"xn--pythn-mua.org.")
653c23
 
653c23
+    def test_builtin_decode_length_limit(self):
653c23
+        with self.assertRaisesRegex(UnicodeError, "too long"):
653c23
+            (b"xn--016c"+b"a"*1100).decode("idna")
653c23
+        with self.assertRaisesRegex(UnicodeError, "too long"):
653c23
+            (b"xn--016c"+b"a"*70).decode("idna")
653c23
+
653c23
     def test_stream(self):
653c23
         r = codecs.getreader("idna")(io.BytesIO(b"abc"))
653c23
         r.read(3)
653c23
diff --git a/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst b/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
653c23
new file mode 100644
653c23
index 0000000000..5185fac2e2
653c23
--- /dev/null
653c23
+++ b/Misc/NEWS.d/next/Security/2022-11-04-09-29-36.gh-issue-98433.l76c5G.rst
653c23
@@ -0,0 +1,6 @@
653c23
+The IDNA codec decoder used on DNS hostnames by :mod:`socket` or :mod:`asyncio`
653c23
+related name resolution functions no longer involves a quadratic algorithm.
653c23
+This prevents a potential CPU denial of service if an out-of-spec excessive
653c23
+length hostname involving bidirectional characters were decoded. Some protocols
653c23
+such as :mod:`urllib` http ``3xx`` redirects potentially allow for an attacker
653c23
+to supply such a name.