From 94f74ad09e037fbcdc15dd473f7ffc7e0951c726 Mon Sep 17 00:00:00 2001 From: globalshrug Date: Tue, 11 Aug 2026 10:01:52 -0700 Subject: [PATCH] gh-82039: Relax cookiejar.py case-sensitive regex for the inconsequential first line of the cookie file (GH-15673) (cherry picked from commit 1cf7d898287972947f746fd647bd8aa8fc0e5aae) Co-authored-by: globalshrug Co-authored-by: Oleg Iarygin Co-authored-by: Serhiy Storchaka --- Lib/http/cookiejar.py | 3 ++- Lib/test/test_http_cookiejar.py | 25 +++++++++++++++++++ Misc/ACKS | 1 + ...3-02-11-09-49-49.gh-issue-82039.caTE7O.rst | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2023-02-11-09-49-49.gh-issue-82039.caTE7O.rst diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py index 13e5b104a81ea2b..302bd3676a8144d 100644 --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -53,7 +53,8 @@ def _debug(*args): HTTPONLY_ATTR = "HTTPOnly" HTTPONLY_PREFIX = "#HttpOnly_" DEFAULT_HTTP_PORT = str(http.client.HTTP_PORT) -NETSCAPE_MAGIC_RGX = re.compile("#( Netscape)? HTTP Cookie File") +NETSCAPE_MAGIC_RGX = re.compile("#( Netscape)? HTTP Cookie File", + re.IGNORECASE | re.ASCII) MISSING_FILENAME_TEXT = ("a filename was not supplied (nor was the CookieJar " "instance initialised with one)") NETSCAPE_HEADER_TEXT = """\ diff --git a/Lib/test/test_http_cookiejar.py b/Lib/test/test_http_cookiejar.py index 04cb440cd4ccf66..7f39b5c772bd10f 100644 --- a/Lib/test/test_http_cookiejar.py +++ b/Lib/test/test_http_cookiejar.py @@ -459,6 +459,31 @@ def test_bad_magic(self): finally: os_helper.unlink(filename) + def test_magic_ignores_case(self): + filename = os_helper.TESTFN + self.addCleanup(os_helper.unlink, filename) + for magic in ("# Netscape HTTP Cookie File", + "# netscape http cookie file", + "# HTTP Cookie File", + "# http cookie file"): + with self.subTest(magic=magic): + with open(filename, "w") as f: + f.write(magic + "\n") + MozillaCookieJar().load(filename) + + def test_magic_is_not_unicode(self): + # Unicode case folding must not be used: 'ſ' (U+017F) and 'K' + # (U+212A) are case-insensitively equal to 's' and 'k' in Unicode. + filename = os_helper.TESTFN + self.addCleanup(os_helper.unlink, filename) + for magic in ("# Netſcape HTTP Cookie File", + "# Netscape HTTP CooKie File"): + with self.subTest(magic=magic): + with open(filename, "w", encoding="utf-8") as f: + f.write(magic + "\n") + self.assertRaises(LoadError, MozillaCookieJar().load, filename) + + class CookieTests(unittest.TestCase): # XXX # Get rid of string comparisons where not actually testing str / repr. diff --git a/Misc/ACKS b/Misc/ACKS index 154d1e7ce019ec1..742098205ba1935 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -747,6 +747,7 @@ Peter Harris Jonathan Hartley Travis B. Hartwell Henrik Harutyunyan +Ashley Harvey Shane Harvey Larry Hastings Tim Hatch diff --git a/Misc/NEWS.d/next/Library/2023-02-11-09-49-49.gh-issue-82039.caTE7O.rst b/Misc/NEWS.d/next/Library/2023-02-11-09-49-49.gh-issue-82039.caTE7O.rst new file mode 100644 index 000000000000000..cb75ae83780eaf6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-02-11-09-49-49.gh-issue-82039.caTE7O.rst @@ -0,0 +1,2 @@ +:meth:`http.cookiejar.FileCookieJar.load` now checks the first, format +signature line in a case-insensitive manner. Patch by Ashley Harvey.