diff options
| author | Gyorgy Sarvari <skandigraun@gmail.com> | 2026-01-08 08:46:16 +0100 |
|---|---|---|
| committer | Gyorgy Sarvari <skandigraun@gmail.com> | 2026-01-08 22:03:03 +0100 |
| commit | 99de91aa3c37676f6d03cc214232250f973d253d (patch) | |
| tree | bf4ff04e7dc869d2fa011eb161daa4a344e47c79 /meta-python | |
| parent | 0e149e459110ab0fb046658026f0f293f6058e2c (diff) | |
| download | meta-openembedded-99de91aa3c37676f6d03cc214232250f973d253d.tar.gz | |
python3-tornado: patch CVE-2024-52804
Details: https://nvd.nist.gov/vuln/detail/CVE-2024-52804
Pick the patch mentioned by the NVD advisory.
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Diffstat (limited to 'meta-python')
| -rw-r--r-- | meta-python/recipes-devtools/python/python3-tornado/CVE-2024-52804.patch | 142 | ||||
| -rw-r--r-- | meta-python/recipes-devtools/python/python3-tornado_6.1.bb | 4 |
2 files changed, 145 insertions, 1 deletions
diff --git a/meta-python/recipes-devtools/python/python3-tornado/CVE-2024-52804.patch b/meta-python/recipes-devtools/python/python3-tornado/CVE-2024-52804.patch new file mode 100644 index 0000000000..0279c6859c --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-tornado/CVE-2024-52804.patch | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | From b4918d1e62a3f53cdba19d1b1af5938c7b6b1720 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Ben Darnell <ben@bendarnell.com> | ||
| 3 | Date: Thu, 21 Nov 2024 14:48:05 -0500 | ||
| 4 | Subject: [PATCH] httputil: Fix quadratic performance of cookie parsing | ||
| 5 | |||
| 6 | Maliciously-crafted cookies can cause Tornado to | ||
| 7 | spend an unreasonable amount of CPU time and block | ||
| 8 | the event loop. | ||
| 9 | |||
| 10 | This change replaces the quadratic algorithm with | ||
| 11 | a more efficient one. The implementation is copied | ||
| 12 | from the Python 3.13 standard library (the | ||
| 13 | previous one was from Python 3.5). | ||
| 14 | |||
| 15 | Fixes CVE-2024-52804 | ||
| 16 | See CVE-2024-7592 for a similar vulnerability in cpython. | ||
| 17 | |||
| 18 | Thanks to github.com/kexinoh for the report. | ||
| 19 | |||
| 20 | CVE: CVE-2024-52804 | ||
| 21 | Upstream-Status: Backport [https://github.com/tornadoweb/tornado/commit/d5ba4a1695fbf7c6a3e54313262639b198291533] | ||
| 22 | Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com> | ||
| 23 | --- | ||
| 24 | tornado/httputil.py | 38 ++++++++--------------------- | ||
| 25 | tornado/test/httputil_test.py | 46 +++++++++++++++++++++++++++++++++++ | ||
| 26 | 2 files changed, 56 insertions(+), 28 deletions(-) | ||
| 27 | |||
| 28 | diff --git a/tornado/httputil.py b/tornado/httputil.py | ||
| 29 | index bd32cd0..bb50786 100644 | ||
| 30 | --- a/tornado/httputil.py | ||
| 31 | +++ b/tornado/httputil.py | ||
| 32 | @@ -1052,15 +1052,20 @@ def qs_to_qsl(qs: Dict[str, List[AnyStr]]) -> Iterable[Tuple[str, AnyStr]]: | ||
| 33 | yield (k, v) | ||
| 34 | |||
| 35 | |||
| 36 | -_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") | ||
| 37 | -_QuotePatt = re.compile(r"[\\].") | ||
| 38 | -_nulljoin = "".join | ||
| 39 | +_unquote_sub = re.compile(r"\\(?:([0-3][0-7][0-7])|(.))").sub | ||
| 40 | + | ||
| 41 | + | ||
| 42 | +def _unquote_replace(m: re.Match) -> str: | ||
| 43 | + if m[1]: | ||
| 44 | + return chr(int(m[1], 8)) | ||
| 45 | + else: | ||
| 46 | + return m[2] | ||
| 47 | |||
| 48 | |||
| 49 | def _unquote_cookie(s: str) -> str: | ||
| 50 | """Handle double quotes and escaping in cookie values. | ||
| 51 | |||
| 52 | - This method is copied verbatim from the Python 3.5 standard | ||
| 53 | + This method is copied verbatim from the Python 3.13 standard | ||
| 54 | library (http.cookies._unquote) so we don't have to depend on | ||
| 55 | non-public interfaces. | ||
| 56 | """ | ||
| 57 | @@ -1081,30 +1086,7 @@ def _unquote_cookie(s: str) -> str: | ||
| 58 | # \012 --> \n | ||
| 59 | # \" --> " | ||
| 60 | # | ||
| 61 | - i = 0 | ||
| 62 | - n = len(s) | ||
| 63 | - res = [] | ||
| 64 | - while 0 <= i < n: | ||
| 65 | - o_match = _OctalPatt.search(s, i) | ||
| 66 | - q_match = _QuotePatt.search(s, i) | ||
| 67 | - if not o_match and not q_match: # Neither matched | ||
| 68 | - res.append(s[i:]) | ||
| 69 | - break | ||
| 70 | - # else: | ||
| 71 | - j = k = -1 | ||
| 72 | - if o_match: | ||
| 73 | - j = o_match.start(0) | ||
| 74 | - if q_match: | ||
| 75 | - k = q_match.start(0) | ||
| 76 | - if q_match and (not o_match or k < j): # QuotePatt matched | ||
| 77 | - res.append(s[i:k]) | ||
| 78 | - res.append(s[k + 1]) | ||
| 79 | - i = k + 2 | ||
| 80 | - else: # OctalPatt matched | ||
| 81 | - res.append(s[i:j]) | ||
| 82 | - res.append(chr(int(s[j + 1 : j + 4], 8))) | ||
| 83 | - i = j + 4 | ||
| 84 | - return _nulljoin(res) | ||
| 85 | + return _unquote_sub(_unquote_replace, s) | ||
| 86 | |||
| 87 | |||
| 88 | def parse_cookie(cookie: str) -> Dict[str, str]: | ||
| 89 | diff --git a/tornado/test/httputil_test.py b/tornado/test/httputil_test.py | ||
| 90 | index 0fad403..25faf66 100644 | ||
| 91 | --- a/tornado/test/httputil_test.py | ||
| 92 | +++ b/tornado/test/httputil_test.py | ||
| 93 | @@ -519,3 +519,49 @@ class ParseCookieTest(unittest.TestCase): | ||
| 94 | self.assertEqual( | ||
| 95 | parse_cookie(" = b ; ; = ; c = ; "), {"": "b", "c": ""} | ||
| 96 | ) | ||
| 97 | + | ||
| 98 | + def test_unquote(self): | ||
| 99 | + # Copied from | ||
| 100 | + # https://github.com/python/cpython/blob/dc7a2b6522ec7af41282bc34f405bee9b306d611/Lib/test/test_http_cookies.py#L62 | ||
| 101 | + cases = [ | ||
| 102 | + (r'a="b=\""', 'b="'), | ||
| 103 | + (r'a="b=\\"', "b=\\"), | ||
| 104 | + (r'a="b=\="', "b=="), | ||
| 105 | + (r'a="b=\n"', "b=n"), | ||
| 106 | + (r'a="b=\042"', 'b="'), | ||
| 107 | + (r'a="b=\134"', "b=\\"), | ||
| 108 | + (r'a="b=\377"', "b=\xff"), | ||
| 109 | + (r'a="b=\400"', "b=400"), | ||
| 110 | + (r'a="b=\42"', "b=42"), | ||
| 111 | + (r'a="b=\\042"', "b=\\042"), | ||
| 112 | + (r'a="b=\\134"', "b=\\134"), | ||
| 113 | + (r'a="b=\\\""', 'b=\\"'), | ||
| 114 | + (r'a="b=\\\042"', 'b=\\"'), | ||
| 115 | + (r'a="b=\134\""', 'b=\\"'), | ||
| 116 | + (r'a="b=\134\042"', 'b=\\"'), | ||
| 117 | + ] | ||
| 118 | + for encoded, decoded in cases: | ||
| 119 | + with self.subTest(encoded): | ||
| 120 | + c = parse_cookie(encoded) | ||
| 121 | + self.assertEqual(c["a"], decoded) | ||
| 122 | + | ||
| 123 | + def test_unquote_large(self): | ||
| 124 | + # Adapted from | ||
| 125 | + # https://github.com/python/cpython/blob/dc7a2b6522ec7af41282bc34f405bee9b306d611/Lib/test/test_http_cookies.py#L87 | ||
| 126 | + # Modified from that test because we handle semicolons differently from the stdlib. | ||
| 127 | + # | ||
| 128 | + # This is a performance regression test: prior to improvements in Tornado 6.4.2, this test | ||
| 129 | + # would take over a minute with n= 100k. Now it runs in tens of milliseconds. | ||
| 130 | + n = 100000 | ||
| 131 | + for encoded in r"\\", r"\134": | ||
| 132 | + with self.subTest(encoded): | ||
| 133 | + start = time.time() | ||
| 134 | + data = 'a="b=' + encoded * n + '"' | ||
| 135 | + value = parse_cookie(data)["a"] | ||
| 136 | + end = time.time() | ||
| 137 | + self.assertEqual(value[:3], "b=\\") | ||
| 138 | + self.assertEqual(value[-3:], "\\\\\\") | ||
| 139 | + self.assertEqual(len(value), n + 2) | ||
| 140 | + | ||
| 141 | + # Very loose performance check to avoid false positives | ||
| 142 | + self.assertLess(end - start, 1, "Test took too long") | ||
diff --git a/meta-python/recipes-devtools/python/python3-tornado_6.1.bb b/meta-python/recipes-devtools/python/python3-tornado_6.1.bb index d4cb58febc..0d96cbd10e 100644 --- a/meta-python/recipes-devtools/python/python3-tornado_6.1.bb +++ b/meta-python/recipes-devtools/python/python3-tornado_6.1.bb | |||
| @@ -6,7 +6,9 @@ HOMEPAGE = "http://www.tornadoweb.org/en/stable/" | |||
| 6 | LICENSE = "Apache-2.0" | 6 | LICENSE = "Apache-2.0" |
| 7 | LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" | 7 | LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" |
| 8 | 8 | ||
| 9 | SRC_URI += "file://CVE-2023-28370.patch" | 9 | SRC_URI += "file://CVE-2023-28370.patch \ |
| 10 | file://CVE-2024-52804.patch \ | ||
| 11 | " | ||
| 10 | SRC_URI[md5sum] = "f324f5e7607798552359d6ab054c4321" | 12 | SRC_URI[md5sum] = "f324f5e7607798552359d6ab054c4321" |
| 11 | SRC_URI[sha256sum] = "33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791" | 13 | SRC_URI[sha256sum] = "33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791" |
| 12 | 14 | ||
