https://github.com/python/cpython/commit/4c3e2114b5887592612baa14f09988867234dbe6
commit: 4c3e2114b5887592612baa14f09988867234dbe6
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: picnixz <[email protected]>
date: 2025-12-28T15:14:04Z
summary:

[3.14] gh-143241: Fix infinite loop in `zoneinfo._common.load_data` (GH-143243) 
(#143251)

gh-143241: Fix infinite loop in `zoneinfo._common.load_data` (GH-143243)

Correctly reject truncated TZif files in `ZoneInfo.from_file`.

---------
(cherry picked from commit 3ca1f2a370e44874d0dc8c82a01465e0171bec5c)

Co-authored-by: Fatih Çelik <[email protected]>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-12-28-13-49-06.gh-issue-143241.5H4b8d.rst
M Doc/library/zoneinfo.rst
M Lib/test/test_zoneinfo/test_zoneinfo.py
M Lib/zoneinfo/_common.py

diff --git a/Doc/library/zoneinfo.rst b/Doc/library/zoneinfo.rst
index d95260896f75e1..efd28b31ef2a98 100644
--- a/Doc/library/zoneinfo.rst
+++ b/Doc/library/zoneinfo.rst
@@ -206,6 +206,9 @@ The ``ZoneInfo`` class has two alternate constructors:
 
     Objects created via this constructor cannot be pickled (see `pickling`_).
 
+    :exc:`ValueError` is raised if the data read from *file_obj* is not a valid
+    TZif file.
+
 .. classmethod:: ZoneInfo.no_cache(key)
 
     An alternate constructor that bypasses the constructor's cache. It is
diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py 
b/Lib/test/test_zoneinfo/test_zoneinfo.py
index df7f0d82a2eac9..88d79b258cdf7a 100644
--- a/Lib/test/test_zoneinfo/test_zoneinfo.py
+++ b/Lib/test/test_zoneinfo/test_zoneinfo.py
@@ -252,6 +252,8 @@ def test_bad_zones(self):
         bad_zones = [
             b"",  # Empty file
             b"AAAA3" + b" " * 15,  # Bad magic
+            # Truncated V2 file (should not loop indefinitely)
+            b"TZif2" + (b"\x00" * 39) + b"TZif2" + (b"\x00" * 39) + b"\n" + 
b"Part",
         ]
 
         for bad_zone in bad_zones:
diff --git a/Lib/zoneinfo/_common.py b/Lib/zoneinfo/_common.py
index 03cc42149f9b74..59f3f0ce853f74 100644
--- a/Lib/zoneinfo/_common.py
+++ b/Lib/zoneinfo/_common.py
@@ -118,11 +118,10 @@ def get_abbr(idx):
         c = fobj.read(1)  # Should be \n
         assert c == b"\n", c
 
-        tz_bytes = b""
-        while (c := fobj.read(1)) != b"\n":
-            tz_bytes += c
-
-        tz_str = tz_bytes
+        line = fobj.readline()
+        if not line.endswith(b"\n"):
+            raise ValueError("Invalid TZif file: unexpected end of file")
+        tz_str = line.rstrip(b"\n")
     else:
         tz_str = None
 
diff --git 
a/Misc/NEWS.d/next/Library/2025-12-28-13-49-06.gh-issue-143241.5H4b8d.rst 
b/Misc/NEWS.d/next/Library/2025-12-28-13-49-06.gh-issue-143241.5H4b8d.rst
new file mode 100644
index 00000000000000..7170a06015ee7c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-12-28-13-49-06.gh-issue-143241.5H4b8d.rst
@@ -0,0 +1,2 @@
+:mod:`zoneinfo`: fix infinite loop in :meth:`ZoneInfo.from_file
+<zoneinfo.ZoneInfo.from_file>` when parsing a malformed TZif file. Patch by 
Fatih Celik.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to