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

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