diff --git a/src/header/time/mod.rs b/src/header/time/mod.rs index 06d5ccc8e3..b4c708042a 100644 --- a/src/header/time/mod.rs +++ b/src/header/time/mod.rs @@ -23,7 +23,7 @@ use crate::{ }; use alloc::collections::BTreeSet; use chrono::{ - DateTime, Datelike, FixedOffset, NaiveDate, NaiveDateTime, Offset, TimeZone, Timelike, Utc, + DateTime, Datelike, NaiveDate, NaiveDateTime, Offset, TimeZone, Timelike, Utc, offset::MappedLocalTime, }; use chrono_tz::{OffsetComponents, OffsetName, Tz}; @@ -451,19 +451,22 @@ pub unsafe extern "C" fn mktime(timeptr: *mut tm) -> time_t { } }; - let offset = get_offset(unsafe { (*timeptr).tm_gmtoff }).unwrap(); let tz = time_zone(); - // Create DateTime - let datetime = match offset.from_local_datetime(&naive_local) { + let isdst = unsafe { (*timeptr).tm_isdst }; + let tz_datetime = match tz.from_local_datetime(&naive_local) { MappedLocalTime::Single(datetime) => datetime, - _ => { + MappedLocalTime::Ambiguous(early, late) => { + if isdst > 0 { + early + } else { + late + } + } + MappedLocalTime::None => { platform::ERRNO.set(EOVERFLOW); return -1; } }; - - // Convert to UTC and get timestamp - let tz_datetime = datetime.with_timezone(&tz); let timestamp = tz_datetime.timestamp(); unsafe { ptr::write(timeptr, datetime_to_tm(&tz_datetime)) }; @@ -859,15 +862,6 @@ unsafe fn set_timezone( } } -#[inline(always)] -pub const fn get_offset(off: c_long) -> Option { - if off < 0 { - FixedOffset::west_opt(off as _) - } else { - FixedOffset::east_opt(off as _) - } -} - const fn blank_tm() -> tm { tm { tm_year: 0, diff --git a/tests/expected/time/mktime.stdout b/tests/expected/time/mktime.stdout index c9b309e63c..b351ff41f3 100644 --- a/tests/expected/time/mktime.stdout +++ b/tests/expected/time/mktime.stdout @@ -4,3 +4,4 @@ -500 = -500 0 = 0 1531454950 = 1531454950 +gmtoff_ignored = 1 diff --git a/tests/time/mktime.c b/tests/time/mktime.c index bc8c9c755d..beaf01c4ef 100644 --- a/tests/time/mktime.c +++ b/tests/time/mktime.c @@ -57,4 +57,16 @@ int main(void) { printf("Comparison %ld == %ld failed. Time: %s", input, output, asctime(time)); } } + + // mktime must not panic on out-of-range tm_gmtoff + { + struct tm tg = { 0 }; + tg.tm_year = 124; + tg.tm_mon = 0; + tg.tm_mday = 1; + tg.tm_hour = 12; + tg.tm_gmtoff = 100000; + time_t result = mktime(&tg); + printf("gmtoff_ignored = %d\n", result != (time_t)-1); + } }