From 59b36dd4264661ccfe4f624fd8912de37d2607f3 Mon Sep 17 00:00:00 2001 From: youknowdot Date: Fri, 9 Oct 2026 07:29:16 -0700 Subject: [PATCH] _zoneinfo: reject empty quoted POSIX TZ abbreviations (#9017) * Reject empty quoted POSIX timezone abbreviations Split the Python 3.14-compatible parser guard from #8954. Cover empty standard and daylight-saving abbreviations and preserve valid quoted names. Assisted-by: OpenAI Codex:model identifier unavailable * Keep zoneinfo regression in module snippet Rename the snippet as requested during review without changing test contents. Assisted-by: OpenAI Codex:model identifier unavailable --- crates/stdlib/src/_zoneinfo.rs | 3 +++ extra_tests/snippets/stdlib_zoneinfo.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 extra_tests/snippets/stdlib_zoneinfo.py diff --git a/crates/stdlib/src/_zoneinfo.rs b/crates/stdlib/src/_zoneinfo.rs index 9ab94cbef..aea7db10b 100644 --- a/crates/stdlib/src/_zoneinfo.rs +++ b/crates/stdlib/src/_zoneinfo.rs @@ -552,6 +552,9 @@ mod _zoneinfo { parser.bump(); } let end = parser.i; + if end == start { + return None; + } parser.bump(); return Some(String::from_utf8_lossy(&parser.bytes[start..end]).into_owned()); } diff --git a/extra_tests/snippets/stdlib_zoneinfo.py b/extra_tests/snippets/stdlib_zoneinfo.py new file mode 100644 index 000000000..c8004585f --- /dev/null +++ b/extra_tests/snippets/stdlib_zoneinfo.py @@ -0,0 +1,19 @@ +import io +import struct +from zoneinfo import ZoneInfo + +from testutils import assert_raises + +# Minimal TZif v3 data with no transitions and a POSIX rule in the footer. +header = (b"TZif3" + b"\0" * 15 + struct.pack(">6l", 0, 0, 0, 0, 0, 0)) * 2 + + +def zone_from_rule(rule): + return ZoneInfo.from_file(io.BytesIO(header + b"\n" + rule + b"\n")) + + +for rule in (b"<>5", b"AAA4<>,M3.2.0/2,M11.1.0/3"): + assert_raises(ValueError, zone_from_rule, rule) + +# Quoting still permits nonempty numeric abbreviations. +assert zone_from_rule(b"<+05>-5").tzname(None) == "+05"