From e5a4add00f28f8eec1f40e60cb15ff0d6afb6585 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 26 Oct 2021 15:08:08 -0700 Subject: [PROPOSED] Fix uninitialized variable bug Problem reported by Christos Zoulas. * NEWS: Mention this. * localtime.c (tzloadbody): Check that the leap seconds in the TZif file are sorted, even if they occur after the maximum time_t value. This avoids accessing an uninitialized variable 'prevcorr' on a 32-bit time_t machine reading malformed 64-bit TZif data. --- NEWS | 5 +++++ localtime.c | 31 ++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index d83e01c..d4a9823 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,11 @@ Unreleased, experimental changes past practice. The first differing prediction is a fallback on 2025-10-24, not 2025-10-31. + Changes to code + + Fix bug when 32-bit time_t code reads malformed 64-bit TZif data. + (Problem reported by Christos Zoulas.) + Release 2021e - 2021-10-21 18:41:00 -0700 diff --git a/localtime.c b/localtime.c index 6a687d7..6d736b2 100644 --- a/localtime.c +++ b/localtime.c @@ -526,24 +526,29 @@ tzloadbody(char const *name, struct state *sp, bool doextend, int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p); int_fast32_t corr = detzcode(p + stored); p += stored + 4; + /* Leap seconds cannot occur before the Epoch, or out of order. */ if (tr <= prevtr) return EINVAL; + + /* To avoid other botches in this code, each leap second's + correction must differ from the previous one's by 1 + second or less, except that the first correction can be + any value; these requirements are more generous than + RFC 8536, to allow future RFC extensions. */ + if (! (i == 0 + || (prevcorr < corr + ? corr == prevcorr + 1 + : (corr == prevcorr + || corr == prevcorr - 1)))) + return EINVAL; + prevtr = tr; + prevcorr = corr; + if (tr <= TIME_T_MAX) { - /* To avoid other botches in this code, each leap second's - correction must differ from the previous one's by 1 - second or less, except that the first correction can be - any value; these requirements are more generous than - RFC 8536, to allow future RFC extensions. */ - if (! (i == 0 - || (prevcorr < corr - ? corr == prevcorr + 1 - : (corr == prevcorr - || corr == prevcorr - 1)))) - return EINVAL; - sp->lsis[leapcnt].ls_trans = prevtr = tr; - sp->lsis[leapcnt].ls_corr = prevcorr = corr; + sp->lsis[leapcnt].ls_trans = tr; + sp->lsis[leapcnt].ls_corr = corr; leapcnt++; } } -- 2.31.1