From: datauwu Date: Sat, 1 Aug 2026 18:57:11 +0000 (+0800) Subject: warc: fix UB signed overflow in time conversion X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c84de7963ce2bf26d96bc2a11b63c2a73d43fdb6;p=thirdparty%2Flibarchive.git warc: fix UB signed overflow in time conversion Use checked 64-bit math when timegm() is not available. Reject values outside time_t instead of overflowing signed integers. --- diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c index d70c71832..87238c7e1 100644 --- a/libarchive/archive_read_support_format_warc.c +++ b/libarchive/archive_read_support_format_warc.c @@ -552,19 +552,29 @@ time_from_tm(struct tm *t) /* Use platform timegm() if available. */ return (timegm(t)); #else + int64_t days, result; + /* Otherwise, calculate directly using POSIX assumptions. */ /* First, fix up tm_yday based on the year, month, and day. */ if (mktime(t) == (time_t)-1) return ((time_t)-1); /* Then compute timegm() from first principles. */ - return (t->tm_sec - + t->tm_min * 60 - + t->tm_hour * 3600 - + t->tm_yday * 86400 - + (t->tm_year - 70) * 31536000 - + ((t->tm_year - 69) / 4) * 86400 - - ((t->tm_year - 1) / 100) * 86400 - + ((t->tm_year + 299) / 400) * 86400); + days = (int64_t)t->tm_yday + + ((int64_t)t->tm_year - 70) * 365 + + ((int64_t)t->tm_year - 69) / 4 + - ((int64_t)t->tm_year - 1) / 100 + + ((int64_t)t->tm_year + 299) / 400; + if (archive_ckd_mul_i64(&result, days, 86400) || + archive_ckd_add_i64(&result, result, + (int64_t)t->tm_hour * 3600 + t->tm_min * 60 + + t->tm_sec)) + return ((time_t)-1); + if (result < 0) { + if (TIME_MIN == 0 || result < (int64_t)TIME_MIN) + return ((time_t)-1); + } else if ((uint64_t)result > (uint64_t)TIME_MAX) + return ((time_t)-1); + return ((time_t)result); #endif }