From 8680fa4451c62624a70944d98b2d8ba1ae788419 Mon Sep 17 00:00:00 2001 From: LamentXU <108666168+LamentXU123@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:42:20 +0800 Subject: [PATCH 01/24] Update uuid.rst --- Doc/library/uuid.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 92d58024e84d4e..109e70c7665dce 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -193,9 +193,12 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid1(node=None, clock_seq=None) - Generate a UUID from a host ID, sequence number, and the current time. If *node* - is not given, :func:`getnode` is used to obtain the hardware address. If - *clock_seq* is given, it is used as the sequence number; otherwise a random + Generate a UUID from a host ID, sequence number, and the current time + according to :rfc:`RFC 9562, §5.1 <9562#section-5.1>`. + + If *node* is not given, :func:`getnode` is used to obtain the hardware address. + + If *clock_seq* is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. @@ -203,25 +206,29 @@ The :mod:`uuid` module defines the following functions: Generate a UUID based on the MD5 hash of a namespace identifier (which is a UUID) and a name (which is a :class:`bytes` object or a string - that will be encoded using UTF-8). + that will be encoded using UTF-8) + according to :rfc:`RFC 9562, §5.3 <9562#section-5.3>`. .. function:: uuid4() - Generate a random UUID. + Generate a random UUID in a cryptographically-secure method + according to :rfc:`RFC 9562, §5.4 <9562#section-5.4>`. .. function:: uuid5(namespace, name) Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a UUID) and a name (which is a :class:`bytes` object or a string - that will be encoded using UTF-8). + that will be encoded using UTF-8) + according to :rfc:`RFC 9562, §5.5 <9562#section-5.5>`. .. function:: uuid6(node=None, clock_seq=None) Generate a UUID from a sequence number and the current time according to - :rfc:`9562`. + :rfc:`RFC 9562, §5.6 <9562#section-5.6>`. + This is an alternative to :func:`uuid1` to improve database locality. When *node* is not specified, :func:`getnode` is used to obtain the hardware From b911f1e78dc7a3ad7b016655cee2a9797761e212 Mon Sep 17 00:00:00 2001 From: LamentXU <108666168+LamentXU123@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:49:20 +0800 Subject: [PATCH 02/24] Update uuid.rst --- Doc/library/uuid.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 109e70c7665dce..9ec3615b8d0b64 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -193,11 +193,11 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid1(node=None, clock_seq=None) - Generate a UUID from a host ID, sequence number, and the current time + Generate a UUID from a host ID, sequence number, and the current time according to :rfc:`RFC 9562, §5.1 <9562#section-5.1>`. If *node* is not given, :func:`getnode` is used to obtain the hardware address. - + If *clock_seq* is given, it is used as the sequence number; otherwise a random 14-bit sequence number is chosen. From c69a050b885928dd5cb8afb578a9433a8b9769d0 Mon Sep 17 00:00:00 2001 From: LamentXU <108666168+LamentXU123@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:47:19 +0800 Subject: [PATCH 03/24] Update Doc/library/uuid.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/uuid.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 9ec3615b8d0b64..6e858afa5d0ab7 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -196,9 +196,9 @@ The :mod:`uuid` module defines the following functions: Generate a UUID from a host ID, sequence number, and the current time according to :rfc:`RFC 9562, §5.1 <9562#section-5.1>`. - If *node* is not given, :func:`getnode` is used to obtain the hardware address. - - If *clock_seq* is given, it is used as the sequence number; otherwise a random + When *node* is not specified, :func:`getnode` is used to obtain the hardware + address as a 48-bit positive integer. When a sequence number *clock_seq* is + not specified, a pseudo-random 14-bit positive integer is generated. 14-bit sequence number is chosen. From b55a920f95333206e93f5e252eca4f06037a0667 Mon Sep 17 00:00:00 2001 From: LamentXU <108666168+LamentXU123@users.noreply.github.com> Date: Fri, 20 Jun 2025 08:25:13 +0800 Subject: [PATCH 04/24] Update uuid.rst --- Doc/library/uuid.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 6e858afa5d0ab7..a34c7723caa20e 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -199,7 +199,6 @@ The :mod:`uuid` module defines the following functions: When *node* is not specified, :func:`getnode` is used to obtain the hardware address as a 48-bit positive integer. When a sequence number *clock_seq* is not specified, a pseudo-random 14-bit positive integer is generated. - 14-bit sequence number is chosen. .. function:: uuid3(namespace, name) From f1290535de757a2bd3a88093792da9ae3b08cf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:58:19 +0200 Subject: [PATCH 05/24] sync uuid1 & uuid6 docs --- Doc/library/uuid.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index a34c7723caa20e..6698e6d3f43c43 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -200,6 +200,9 @@ The :mod:`uuid` module defines the following functions: address as a 48-bit positive integer. When a sequence number *clock_seq* is not specified, a pseudo-random 14-bit positive integer is generated. + If *node* or *clock_seq* exceed their expected bit count, + only their least significant bits are kept. + .. function:: uuid3(namespace, name) @@ -234,8 +237,8 @@ The :mod:`uuid` module defines the following functions: address as a 48-bit positive integer. When a sequence number *clock_seq* is not specified, a pseudo-random 14-bit positive integer is generated. - If *node* or *clock_seq* exceed their expected bit count, only their least - significant bits are kept. + If *node* or *clock_seq* exceed their expected bit count, + only their least significant bits are kept. .. versionadded:: 3.14 From 48064f29a36c4000f3232243a4ded06a772006a3 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 28 Jun 2025 21:51:45 +0800 Subject: [PATCH 06/24] Update cookiejar.py --- Lib/http/cookiejar.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 68cf16c93cc1c8..44d59b91a154f7 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -656,10 +656,9 @@ def request_path(request): return path def request_port(request): - host = request.host - i = host.find(':') - if i >= 0: - port = host[i+1:] + match = cut_port_re.search(request.host) + if match: + port = match.group(0).removeprefix(':') try: int(port) except ValueError: From e1fe548dfde958e9b9b3756625f239a348d641fd Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 28 Jun 2025 21:52:17 +0800 Subject: [PATCH 07/24] Update test_http_cookiejar.py --- Lib/test/test_http_cookiejar.py | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 04cb440cd4ccf6..a9cc7eae8bf8f4 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1262,6 +1262,40 @@ def test_missing_final_slash(self): c.add_cookie_header(req) self.assertTrue(req.has_header("Cookie")) + def test_set_ok_port(self): + pol = DefaultCookiePolicy( + rfc2965=True, blocked_domains=[]) + c = CookieJar(policy=pol) + headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + req = urllib.request.Request("http://127.0.0.1:1234") + res = FakeResponse(headers, "http://127.0.0.1:1234") + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + + c.clear() + + req = urllib.request.Request("http://[::1]:1234") + res = FakeResponse(headers, "http://[::1]:1234") + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + + def test_return_ok_port(self): + pol = DefaultCookiePolicy( + rfc2965=True, blocked_domains=[]) + c = CookieJar(policy=pol) + headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + req = urllib.request.Request("http://127.0.0.1:1234") + res = FakeResponse(headers, "http://127.0.0.1:1234") + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + + c.clear() + + req = urllib.request.Request("http://[::1]:1234") + res = FakeResponse(headers, "http://[::1]:1234") + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + def test_domain_mirror(self): pol = DefaultCookiePolicy(rfc2965=True) From 05597f86f3742fd9bb415c254f9cd87980353ede Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 28 Jun 2025 14:10:09 +0000 Subject: [PATCH 08/24] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst diff --git a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst new file mode 100644 index 00000000000000..ee37a426e9d5bd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst @@ -0,0 +1 @@ +:mod:`http.cookiejar` Fix the bug happens when trying to prase ports of a IPv6 address in :class:`~http.cookiejar.DefaultCookiePolicy` From c5ca056ade07b4f45d1dac5cbc5b34bf90bcec8d Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:35:29 +0800 Subject: [PATCH 09/24] add more test for HDNs --- Lib/test/test_http_cookiejar.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index a9cc7eae8bf8f4..2cee9174e7e77f 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1274,6 +1274,13 @@ def test_set_ok_port(self): c.clear() + req = urllib.request.Request("http://acme.com:1234") + res = FakeResponse(headers, "http://acme.com:1234") + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + + c.clear() + req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) @@ -1291,6 +1298,13 @@ def test_return_ok_port(self): c.clear() + req = urllib.request.Request("http://acme.com:1234") + res = FakeResponse(headers, "http://acme.com:1234") + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + + c.clear() + req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) From 854422d9bb7641783bab02c361a6b3bb26e12ae7 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:48:45 +0800 Subject: [PATCH 10/24] add False test --- Lib/test/test_http_cookiejar.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 2cee9174e7e77f..dbc222d3e3d868 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1286,6 +1286,13 @@ def test_set_ok_port(self): self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + c.clear() + + req = urllib.request.Request("http://[::1]:1235") + res = FakeResponse(headers, "http://[::1]:1235") + self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + def test_return_ok_port(self): pol = DefaultCookiePolicy( rfc2965=True, blocked_domains=[]) @@ -1310,6 +1317,13 @@ def test_return_ok_port(self): self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + c.clear() + + req = urllib.request.Request("http://[::1]:1235") + res = FakeResponse(headers, "http://[::1]:1235") + self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + def test_domain_mirror(self): pol = DefaultCookiePolicy(rfc2965=True) From 428096f667b02df752cf6f3297892bd6d033a5ef Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:49:54 +0800 Subject: [PATCH 11/24] Update test_http_cookiejar.py --- Lib/test/test_http_cookiejar.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index dbc222d3e3d868..566eedf93ec5f3 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1270,28 +1270,24 @@ def test_set_ok_port(self): req = urllib.request.Request("http://127.0.0.1:1234") res = FakeResponse(headers, "http://127.0.0.1:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) c.clear() req = urllib.request.Request("http://acme.com:1234") res = FakeResponse(headers, "http://acme.com:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) c.clear() req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) c.clear() req = urllib.request.Request("http://[::1]:1235") res = FakeResponse(headers, "http://[::1]:1235") self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) def test_return_ok_port(self): pol = DefaultCookiePolicy( @@ -1301,28 +1297,23 @@ def test_return_ok_port(self): req = urllib.request.Request("http://127.0.0.1:1234") res = FakeResponse(headers, "http://127.0.0.1:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) c.clear() req = urllib.request.Request("http://acme.com:1234") res = FakeResponse(headers, "http://acme.com:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) c.clear() req = urllib.request.Request("http://[::1]:1235") res = FakeResponse(headers, "http://[::1]:1235") self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) def test_domain_mirror(self): pol = DefaultCookiePolicy(rfc2965=True) From 312f66fc507a8c2dc06d06d35f85815448e71075 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:22:12 +0800 Subject: [PATCH 12/24] Update Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- .../Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst index ee37a426e9d5bd..21c13398b97761 100644 --- a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst +++ b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst @@ -1 +1,2 @@ -:mod:`http.cookiejar` Fix the bug happens when trying to prase ports of a IPv6 address in :class:`~http.cookiejar.DefaultCookiePolicy` +:mod:`http.cookiejar`: Fix a bug that occurs when :class:`~http.cookiejar.DefaultCookiePolicy` +attempts to parse the port of an IPv6 address. From 94bb9abbafeac9ab97efcf5561046730c79f898f Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sun, 29 Jun 2025 11:21:47 +0800 Subject: [PATCH 13/24] remove useless `c.clear()` --- Lib/test/test_http_cookiejar.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 566eedf93ec5f3..50838aa825e66d 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1271,20 +1271,14 @@ def test_set_ok_port(self): res = FakeResponse(headers, "http://127.0.0.1:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() - req = urllib.request.Request("http://acme.com:1234") res = FakeResponse(headers, "http://acme.com:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() - req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() - req = urllib.request.Request("http://[::1]:1235") res = FakeResponse(headers, "http://[::1]:1235") self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) @@ -1298,19 +1292,14 @@ def test_return_ok_port(self): res = FakeResponse(headers, "http://127.0.0.1:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() - req = urllib.request.Request("http://acme.com:1234") res = FakeResponse(headers, "http://acme.com:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() req = urllib.request.Request("http://[::1]:1234") res = FakeResponse(headers, "http://[::1]:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) - c.clear() - req = urllib.request.Request("http://[::1]:1235") res = FakeResponse(headers, "http://[::1]:1235") self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) From 24eb5d991c3eeca8ff688117aa9b4464ef12b95b Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sun, 29 Jun 2025 11:23:10 +0800 Subject: [PATCH 14/24] Update test_http_cookiejar.py --- Lib/test/test_http_cookiejar.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 50838aa825e66d..0a799e4da6b5af 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -1263,8 +1263,7 @@ def test_missing_final_slash(self): self.assertTrue(req.has_header("Cookie")) def test_set_ok_port(self): - pol = DefaultCookiePolicy( - rfc2965=True, blocked_domains=[]) + pol = DefaultCookiePolicy() c = CookieJar(policy=pol) headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] req = urllib.request.Request("http://127.0.0.1:1234") @@ -1284,8 +1283,7 @@ def test_set_ok_port(self): self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) def test_return_ok_port(self): - pol = DefaultCookiePolicy( - rfc2965=True, blocked_domains=[]) + pol = DefaultCookiePolicy() c = CookieJar(policy=pol) headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] req = urllib.request.Request("http://127.0.0.1:1234") From 0415d3fa8f6674087cfef6dc7584d8623de1c450 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sun, 29 Jun 2025 11:36:09 +0800 Subject: [PATCH 15/24] Update 2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst --- .../next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst index 21c13398b97761..bcdbc665df0294 100644 --- a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst +++ b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst @@ -1,2 +1,2 @@ :mod:`http.cookiejar`: Fix a bug that occurs when :class:`~http.cookiejar.DefaultCookiePolicy` -attempts to parse the port of an IPv6 address. +attempts to parse the port of an IPv6 address in func ``request_port()``. From 357b9d16cb1a1a2b73db68ef3b59d9d1eb1654d4 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 12 Jul 2025 03:07:46 +0800 Subject: [PATCH 16/24] Update test_http_cookiejar.py --- Lib/test/test_http_cookiejar.py | 59 +++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 0a799e4da6b5af..1970b993d6acdf 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -839,6 +839,19 @@ def test_request_port(self): req = urllib.request.Request("http://www.acme.com/", headers={"Host": "www.acme.com:4321"}) self.assertEqual(request_port(req), DEFAULT_HTTP_PORT) + req = urllib.request.Request("http://www.acme.com:", + headers={"Host": "www.acme.com:4321"}) + self.assertEqual(request_port(req), DEFAULT_HTTP_PORT) + req = urllib.request.Request("http://www.acme.com:not_a_port", + headers={"Host": "www.acme.com:4321"}) + self.assertEqual(request_port(req), DEFAULT_HTTP_PORT) + req = urllib.request.Request("http://[::1]:1234", + headers={"Host": "[::1]:4321"}) + self.assertEqual(request_port(req), "1234") + req = urllib.request.Request("http://[::1]", + headers={"Host": "[::1]:4321"}) + self.assertEqual(request_port(req), DEFAULT_HTTP_PORT) + def test_request_host(self): # this request is illegal (RFC2616, 14.2.3) @@ -1265,41 +1278,67 @@ def test_missing_final_slash(self): def test_set_ok_port(self): pol = DefaultCookiePolicy() c = CookieJar(policy=pol) - headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + headers_with_port_1234 = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + headers_with_default_port = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=80"] req = urllib.request.Request("http://127.0.0.1:1234") - res = FakeResponse(headers, "http://127.0.0.1:1234") + res = FakeResponse(headers_with_port_1234, "http://127.0.0.1:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://acme.com:1234") - res = FakeResponse(headers, "http://acme.com:1234") + res = FakeResponse(headers_with_port_1234, "http://acme.com:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://[::1]:1234") - res = FakeResponse(headers, "http://[::1]:1234") + res = FakeResponse(headers_with_port_1234, "http://[::1]:1234") self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://[::1]:1235") - res = FakeResponse(headers, "http://[::1]:1235") + res = FakeResponse(headers_with_port_1234, "http://[::1]:1235") + self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + + req = urllib.request.Request("http://acme.com:") + res = FakeResponse(headers_with_default_port, "http://acme.com:") + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + res = FakeResponse(headers_with_port_1234, "http://acme.com:") + self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + + req = urllib.request.Request("http://acme.com:not_a_port") + res = FakeResponse(headers_with_default_port, "http://acme.com:not_a_port") + self.assertTrue(pol.set_ok_port(c.make_cookies(res, req)[0], req)) + res = FakeResponse(headers_with_port_1234, "http://acme.com:not_a_port") self.assertFalse(pol.set_ok_port(c.make_cookies(res, req)[0], req)) def test_return_ok_port(self): pol = DefaultCookiePolicy() c = CookieJar(policy=pol) - headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + headers_with_port_1234 = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=1234"] + headers_with_default_port = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; port=80"] req = urllib.request.Request("http://127.0.0.1:1234") - res = FakeResponse(headers, "http://127.0.0.1:1234") + res = FakeResponse(headers_with_port_1234, "http://127.0.0.1:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://acme.com:1234") - res = FakeResponse(headers, "http://acme.com:1234") + res = FakeResponse(headers_with_port_1234, "http://acme.com:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://[::1]:1234") - res = FakeResponse(headers, "http://[::1]:1234") + res = FakeResponse(headers_with_port_1234, "http://[::1]:1234") self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) req = urllib.request.Request("http://[::1]:1235") - res = FakeResponse(headers, "http://[::1]:1235") + res = FakeResponse(headers_with_port_1234, "http://[::1]:1235") + self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + + req = urllib.request.Request("http://acme.com:") + res = FakeResponse(headers_with_default_port, "http://acme.com:") + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + res = FakeResponse(headers_with_port_1234, "http://acme.com:") + self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + + req = urllib.request.Request("http://acme.com:not_a_port") + res = FakeResponse(headers_with_default_port, "http://acme.com:not_a_port") + self.assertTrue(pol.return_ok_port(c.make_cookies(res, req)[0], req)) + res = FakeResponse(headers_with_port_1234, "http://acme.com:not_a_port") self.assertFalse(pol.return_ok_port(c.make_cookies(res, req)[0], req)) def test_domain_mirror(self): From 103464792b4710083d31bb593010b0d260b7cb58 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 12 Jul 2025 03:09:05 +0800 Subject: [PATCH 17/24] change to match[0] --- Lib/http/cookiejar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 44d59b91a154f7..03b383579b5094 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -658,7 +658,7 @@ def request_path(request): def request_port(request): match = cut_port_re.search(request.host) if match: - port = match.group(0).removeprefix(':') + port = match[0].removeprefix(':') try: int(port) except ValueError: From 9d75634690cc78fea1666fabd56985ebcca9cbaa Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 12 Jul 2025 21:58:24 +0800 Subject: [PATCH 18/24] Update cookiejar.py --- Lib/http/cookiejar.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 03b383579b5094..10544506d262bd 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -1080,11 +1080,6 @@ def set_ok_port(self, cookie, request): else: req_port = str(req_port) for p in cookie.port.split(","): - try: - int(p) - except ValueError: - _debug(" bad port %s (not numeric)", p) - return False if p == req_port: break else: From b7e859f3e5f1770466b2858217c9449a2dba66d8 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 12 Jul 2025 22:09:41 +0800 Subject: [PATCH 19/24] Update cookiejar.py --- Lib/http/cookiejar.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 10544506d262bd..2fd03940e1eea7 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -659,11 +659,6 @@ def request_port(request): match = cut_port_re.search(request.host) if match: port = match[0].removeprefix(':') - try: - int(port) - except ValueError: - _debug("nonnumeric port: '%s'", port) - return None else: port = DEFAULT_HTTP_PORT return port @@ -1080,6 +1075,11 @@ def set_ok_port(self, cookie, request): else: req_port = str(req_port) for p in cookie.port.split(","): + try: + int(p) + except ValueError: + _debug(" bad port %s (not numeric)", p) + return False if p == req_port: break else: From b7d6e4ed07d6b21092a8dcbd7983ab4e233211e0 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 12 Jul 2025 22:12:13 +0800 Subject: [PATCH 20/24] Update cookiejar.py --- Lib/http/cookiejar.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 2fd03940e1eea7..863cf4cb1f5097 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -1069,11 +1069,7 @@ def set_ok_domain(self, cookie, request): def set_ok_port(self, cookie, request): if cookie.port_specified: - req_port = request_port(request) - if req_port is None: - req_port = "80" - else: - req_port = str(req_port) + req_port = str(request_port(request)) for p in cookie.port.split(","): try: int(p) @@ -1142,8 +1138,6 @@ def return_ok_expires(self, cookie, request): def return_ok_port(self, cookie, request): if cookie.port: req_port = request_port(request) - if req_port is None: - req_port = "80" for p in cookie.port.split(","): if p == req_port: break From d19779692fb06f7f0bed6f64bcf66994ef136629 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:01:59 +0800 Subject: [PATCH 21/24] prevent to remove the debug message --- Lib/http/cookiejar.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 863cf4cb1f5097..94bade52a79918 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -660,9 +660,12 @@ def request_port(request): if match: port = match[0].removeprefix(':') else: + i = request.host.rfind(':') + if (i >= 0 + and not ']' in request.host[i+1:]): # to prevent IPv6 addresses + _debug("nonnumeric port: '%s'", request.host[i+1:]) port = DEFAULT_HTTP_PORT return port - # Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't # need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738). HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()" From bc8bad06d73626d814f99f3765c0a51b413389e3 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:04:10 +0800 Subject: [PATCH 22/24] Update 2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst --- .../next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst index bcdbc665df0294..f2113ec786be1e 100644 --- a/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst +++ b/Misc/NEWS.d/next/Library/2025-06-28-14-10-07.gh-issue-135993.Gmyux9.rst @@ -1,2 +1,2 @@ :mod:`http.cookiejar`: Fix a bug that occurs when :class:`~http.cookiejar.DefaultCookiePolicy` -attempts to parse the port of an IPv6 address in func ``request_port()``. +attempts to parse the port of an IPv6 address in func ``request_port()``. Patch by Weilin Du. From 7e3237a23363cdb618d258607a882a0c44e4a098 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Mon, 14 Jul 2025 17:31:10 +0800 Subject: [PATCH 23/24] Fix CI --- Lib/http/cookiejar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 94bade52a79918..785be6e45a7ba6 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -661,11 +661,12 @@ def request_port(request): port = match[0].removeprefix(':') else: i = request.host.rfind(':') - if (i >= 0 + if (i >= 0 and not ']' in request.host[i+1:]): # to prevent IPv6 addresses _debug("nonnumeric port: '%s'", request.host[i+1:]) port = DEFAULT_HTTP_PORT return port + # Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't # need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738). HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()" From cdda526e1a99ab75ef4a5f43a0c2cee145dc8239 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:13:17 +0800 Subject: [PATCH 24/24] Add stricter check for IPv6 case --- Lib/http/cookiejar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 785be6e45a7ba6..7345cba5a94e51 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -662,7 +662,8 @@ def request_port(request): else: i = request.host.rfind(':') if (i >= 0 - and not ']' in request.host[i+1:]): # to prevent IPv6 addresses + and not ']' in request.host[i+1:] + and not request.host.startswith('[')): # to prevent IPv6 addresses _debug("nonnumeric port: '%s'", request.host[i+1:]) port = DEFAULT_HTTP_PORT return port