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 <fcelik.ft@gmail.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
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
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:
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
--- /dev/null
+:mod:`zoneinfo`: fix infinite loop in :meth:`ZoneInfo.from_file
+<zoneinfo.ZoneInfo.from_file>` when parsing a malformed TZif file. Patch by Fatih Celik.