[PATCH] Fix potential integer overflow in differ_by_repeat
* localtime.c (differ_by_repeat): Remove, since the subtraction t1 - t0 could in theory overflow in 64-bit TZif data. (tzloadbody): Redo to avoid integer overflow. * private.h (SECSPERREPEAT_BITS): Remove; no longer used. --- localtime.c | 30 ++++++++++++++---------------- private.h | 3 +-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/localtime.c b/localtime.c index 9dd496d..9840b89 100644 --- a/localtime.c +++ b/localtime.c @@ -334,14 +334,6 @@ scrub_abbrs(struct state *sp) } } -static bool -differ_by_repeat(const time_t t1, const time_t t0) -{ - if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) - return 0; - return t1 - t0 == SECSPERREPEAT; -} - /* Input buffer for data read from a compiled tz file. */ union input_buffer { /* The first part of the buffer, interpreted as a header. */ @@ -660,20 +652,26 @@ tzloadbody(char const *name, struct state *sp, bool doextend, if (sp->typecnt == 0) return EINVAL; if (sp->timecnt > 1) { + if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) { + time_t repeatat = sp->ats[0] + SECSPERREPEAT; + int repeattype = sp->types[0]; for (i = 1; i < sp->timecnt; ++i) - if (typesequiv(sp, sp->types[i], sp->types[0]) && - differ_by_repeat(sp->ats[i], sp->ats[0])) { + if (sp->ats[i] == repeatat + && typesequiv(sp, sp->types[i], repeattype)) { sp->goback = true; break; - } + } + } + if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) { + time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT; + int repeattype = sp->types[sp->timecnt - 1]; for (i = sp->timecnt - 2; i >= 0; --i) - if (typesequiv(sp, sp->types[sp->timecnt - 1], - sp->types[i]) && - differ_by_repeat(sp->ats[sp->timecnt - 1], - sp->ats[i])) { + if (sp->ats[i] == repeatat + && typesequiv(sp, sp->types[i], repeattype)) { sp->goahead = true; break; - } + } + } } /* Infer sp->defaulttype from the data. Although this default diff --git a/private.h b/private.h index cee3b11..340a354 100644 --- a/private.h +++ b/private.h @@ -642,7 +642,7 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE; #define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t)) /* The extreme time values. These are macros, not constants, so that - any portability problem occur only when compiling .c files that use + any portability problems occur only when compiling .c files that use the macros, which is safer for applications that need only zdump and zic. This implementation assumes no padding if time_t is signed and either the compiler lacks support for _Generic or time_t is not one @@ -727,7 +727,6 @@ char *ctime_r(time_t const *, char *); #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ #define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1) #define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY) -#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ #define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT) #define TM_SUNDAY 0 -- 2.27.0
participants (1)
-
Paul Eggert