Ticket #5910: Python-3.14.4-security_fixes-1.patch
| File Python-3.14.4-security_fixes-1.patch, 7.7 KB (added by , 14 hours ago) |
|---|
-
Lib/http/client.py
Submitted By: Joe Locash Date: 2026-04-13 Initial Package Version: 3.14.4 Upstream Status: Applied Origin: Upstream: https://github.com/python/cpython/pull/148342 https://github.com/python/cpython/pull/148480 Description: Upsream fixes for CVE-2026-1502 and CVE-2026-6100. From afdd351544e8112d4070a31f2218f99256697472 Mon Sep 17 00:00:00 2001 From: Seth Larson <seth@python.org> Date: Fri, 10 Apr 2026 10:21:42 -0500 Subject: [PATCH] gh-146211: Reject CR/LF in HTTP tunnel request headers (GH-146212) (cherry picked from commit 05ed7ce7ae9e17c23a04085b2539fe6d6d3cef69) Co-authored-by: Seth Larson <seth@python.org> Co-authored-by: Illia Volochii <illia.volochii@gmail.com> --- Lib/http/client.py | 11 ++++- Lib/test/test_httplib.py | 45 +++++++++++++++++++ ...-03-20-09-29-42.gh-issue-146211.PQVbs7.rst | 2 + 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index 77f8d26291dfc2..6fb7d254ea9c27 100644a b def _wrap_ipv6(self, ip): 972 972 return ip 973 973 974 974 def _tunnel(self): 975 if _contains_disallowed_url_pchar_re.search(self._tunnel_host): 976 raise ValueError('Tunnel host can\'t contain control characters %r' 977 % (self._tunnel_host,)) 975 978 connect = b"CONNECT %s:%d %s\r\n" % ( 976 979 self._wrap_ipv6(self._tunnel_host.encode("idna")), 977 980 self._tunnel_port, 978 981 self._http_vsn_str.encode("ascii")) 979 982 headers = [connect] 980 983 for header, value in self._tunnel_headers.items(): 981 headers.append(f"{header}: {value}\r\n".encode("latin-1")) 984 header_bytes = header.encode("latin-1") 985 value_bytes = value.encode("latin-1") 986 if not _is_legal_header_name(header_bytes): 987 raise ValueError('Invalid header name %r' % (header_bytes,)) 988 if _is_illegal_header_value(value_bytes): 989 raise ValueError('Invalid header value %r' % (value_bytes,)) 990 headers.append(b"%s: %s\r\n" % (header_bytes, value_bytes)) 982 991 headers.append(b"\r\n") 983 992 # Making a single send() call instead of one per line encourages 984 993 # the host OS to use a more optimal packet size instead of -
Lib/test/test_httplib.py
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index bcb828edec7c39..6f3eac6b98a4de 100644
a b def test_invalid_headers(self): 369 369 with self.assertRaisesRegex(ValueError, 'Invalid header'): 370 370 conn.putheader(name, value) 371 371 372 def test_invalid_tunnel_headers(self): 373 cases = ( 374 ('Invalid\r\nName', 'ValidValue'), 375 ('Invalid\rName', 'ValidValue'), 376 ('Invalid\nName', 'ValidValue'), 377 ('\r\nInvalidName', 'ValidValue'), 378 ('\rInvalidName', 'ValidValue'), 379 ('\nInvalidName', 'ValidValue'), 380 (' InvalidName', 'ValidValue'), 381 ('\tInvalidName', 'ValidValue'), 382 ('Invalid:Name', 'ValidValue'), 383 (':InvalidName', 'ValidValue'), 384 ('ValidName', 'Invalid\r\nValue'), 385 ('ValidName', 'Invalid\rValue'), 386 ('ValidName', 'Invalid\nValue'), 387 ('ValidName', 'InvalidValue\r\n'), 388 ('ValidName', 'InvalidValue\r'), 389 ('ValidName', 'InvalidValue\n'), 390 ) 391 for name, value in cases: 392 with self.subTest((name, value)): 393 conn = client.HTTPConnection('example.com') 394 conn.set_tunnel('tunnel', headers={ 395 name: value 396 }) 397 conn.sock = FakeSocket('') 398 with self.assertRaisesRegex(ValueError, 'Invalid header'): 399 conn._tunnel() # Called in .connect() 400 401 def test_invalid_tunnel_host(self): 402 cases = ( 403 'invalid\r.host', 404 '\ninvalid.host', 405 'invalid.host\r\n', 406 'invalid.host\x00', 407 'invalid host', 408 ) 409 for tunnel_host in cases: 410 with self.subTest(tunnel_host): 411 conn = client.HTTPConnection('example.com') 412 conn.set_tunnel(tunnel_host) 413 conn.sock = FakeSocket('') 414 with self.assertRaisesRegex(ValueError, 'Tunnel host can\'t contain control characters'): 415 conn._tunnel() # Called in .connect() 416 372 417 def test_headers_debuglevel(self): 373 418 body = ( 374 419 b'HTTP/1.1 200 OK\r\n' -
new file Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst
diff --git a/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst b/Misc/NEWS.d/next/Security/2026-03-20-09-29-42.gh-issue-146211.PQVbs7.rst new file mode 100644 index 00000000000000..4993633b8ebebb
- + 1 Reject CR/LF characters in tunnel request headers for the 2 HTTPConnection.set_tunnel() method. -
new file Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst
From c8d8173c4b06d06902c99ec010ad785a30952880 Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <stan@python.org> Date: Mon, 13 Apr 2026 02:14:54 +0100 Subject: [PATCH] gh-148395: Fix a possible UAF in `{LZMA,BZ2,_Zlib}Decompressor` (GH-148396) Fix dangling input pointer after `MemoryError` in _lzma/_bz2/_ZlibDecompressor.decompress (cherry picked from commit 8fc66aef6d7b3ae58f43f5c66f9366cc8cbbfcd2) Co-authored-by: Stan Ulbrych <stan@python.org> --- .../Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst | 5 +++++ Modules/_bz2module.c | 1 + Modules/_lzmamodule.c | 1 + Modules/zlibmodule.c | 1 + 4 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst diff --git a/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst b/Misc/NEWS.d/next/Security/2026-04-10-16-28-21.gh-issue-148395.kfzm0G.rst new file mode 100644 index 00000000000000..9502189ab199c1- + 1 Fix a dangling input pointer in :class:`lzma.LZMADecompressor`, 2 :class:`bz2.BZ2Decompressor`, and internal :class:`!zlib._ZlibDecompressor` 3 when memory allocation fails with :exc:`MemoryError`, which could let a 4 subsequent :meth:`!decompress` call read or write through a stale pointer to 5 the already-released caller buffer. -
Modules/_bz2module.c
diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 9e85e0de42cd8d..055ce82e7d2863 100644
a b decompress(BZ2Decompressor *d, char *data, size_t len, Py_ssize_t max_length) 593 593 return result; 594 594 595 595 error: 596 bzs->next_in = NULL; 596 597 Py_XDECREF(result); 597 598 return NULL; 598 599 } -
Modules/_lzmamodule.c
diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index 462c2181fa6036..6785dc56730c5c 100644
a b decompress(Decompressor *d, uint8_t *data, size_t len, Py_ssize_t max_length) 1120 1120 return result; 1121 1121 1122 1122 error: 1123 lzs->next_in = NULL; 1123 1124 Py_XDECREF(result); 1124 1125 return NULL; 1125 1126 } -
Modules/zlibmodule.c
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 5b6b0c5cac864a..a86aa5fdbb576c 100644
a b decompress(ZlibDecompressor *self, uint8_t *data, 1675 1675 return result; 1676 1676 1677 1677 error: 1678 self->zst.next_in = NULL; 1678 1679 Py_XDECREF(result); 1679 1680 return NULL; 1680 1681 }
