mirror of
https://github.com/python/cpython.git
synced 2026-05-31 14:50:46 +00:00
gh-145883: Fix two heap-buffer-overflows in _zoneinfo (#145885)
This commit is contained in:
parent
328da67b2c
commit
fe9befc1ca
6 changed files with 44 additions and 3 deletions
|
|
@ -741,6 +741,38 @@ def test_empty_zone(self):
|
|||
with self.assertRaises(ValueError):
|
||||
self.klass.from_file(zf)
|
||||
|
||||
def test_invalid_transition_index(self):
|
||||
STD = ZoneOffset("STD", ZERO)
|
||||
DST = ZoneOffset("DST", ONE_H, ONE_H)
|
||||
|
||||
zf = self.construct_zone([
|
||||
ZoneTransition(datetime(2026, 3, 1, 2), STD, DST),
|
||||
ZoneTransition(datetime(2026, 11, 1, 2), DST, STD),
|
||||
], after="", version=1)
|
||||
|
||||
data = bytearray(zf.read())
|
||||
timecnt = struct.unpack_from(">l", data, 32)[0]
|
||||
idx_offset = 44 + timecnt * 4
|
||||
data[idx_offset + 1] = 2 # typecnt is 2, so index 2 is OOB
|
||||
f = io.BytesIO(bytes(data))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.klass.from_file(f)
|
||||
|
||||
def test_transition_lookahead_out_of_bounds(self):
|
||||
STD = ZoneOffset("STD", ZERO)
|
||||
DST = ZoneOffset("DST", ONE_H, ONE_H)
|
||||
EXT = ZoneOffset("EXT", ONE_H)
|
||||
|
||||
zf = self.construct_zone([
|
||||
ZoneTransition(datetime(2026, 3, 1), STD, DST),
|
||||
ZoneTransition(datetime(2026, 6, 1), DST, EXT),
|
||||
ZoneTransition(datetime(2026, 9, 1), EXT, DST),
|
||||
], after="")
|
||||
|
||||
zi = self.klass.from_file(zf)
|
||||
self.assertIsNotNone(zi)
|
||||
|
||||
def test_zone_very_large_timestamp(self):
|
||||
"""Test when a transition is in the far past or future.
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,10 @@ def load_data(fobj):
|
|||
f">{timecnt}{time_type}", fobj.read(timecnt * time_size)
|
||||
)
|
||||
trans_idx = struct.unpack(f">{timecnt}B", fobj.read(timecnt))
|
||||
|
||||
if max(trans_idx) >= typecnt:
|
||||
raise ValueError("Invalid transition index found while reading TZif: "
|
||||
f"{max(trans_idx)}")
|
||||
else:
|
||||
trans_list_utc = ()
|
||||
trans_idx = ()
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ def _utcoff_to_dstoff(trans_idx, utcoffsets, isdsts):
|
|||
if not isdsts[comp_idx]:
|
||||
dstoff = utcoff - utcoffsets[comp_idx]
|
||||
|
||||
if not dstoff and idx < (typecnt - 1):
|
||||
if not dstoff and idx < (typecnt - 1) and i + 1 < len(trans_idx):
|
||||
comp_idx = trans_idx[i + 1]
|
||||
|
||||
# If the following transition is also DST and we couldn't
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
:mod:`zoneinfo`: Fix heap buffer overflow reads from malformed TZif data.
|
||||
Found by OSS Fuzz, issues :oss-fuzz:`492245058` and :oss-fuzz:`492230068`.
|
||||
|
|
@ -1075,7 +1075,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
|
|||
}
|
||||
|
||||
trans_idx[i] = (size_t)cur_trans_idx;
|
||||
if (trans_idx[i] > self->num_ttinfos) {
|
||||
if (trans_idx[i] >= self->num_ttinfos) {
|
||||
PyErr_Format(
|
||||
PyExc_ValueError,
|
||||
"Invalid transition index found while reading TZif: %zd",
|
||||
|
|
@ -2081,7 +2081,7 @@ utcoff_to_dstoff(size_t *trans_idx, long *utcoffs, long *dstoffs,
|
|||
dstoff = utcoff - utcoffs[comp_idx];
|
||||
}
|
||||
|
||||
if (!dstoff && idx < (num_ttinfos - 1)) {
|
||||
if (!dstoff && idx < (num_ttinfos - 1) && i + 1 < num_transitions) {
|
||||
comp_idx = trans_idx[i + 1];
|
||||
|
||||
// If the following transition is also DST and we couldn't find
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@
|
|||
Path("Modules/pyexpat.c"),
|
||||
# zipfile
|
||||
Path("Lib/zipfile/"),
|
||||
# zoneinfo
|
||||
Path("Lib/zoneinfo/"),
|
||||
Path("Modules/_zoneinfo.c"),
|
||||
})
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue