From 0bab4885a793896c6bc566f8a80109c4baeb7bde Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 23 Jun 2023 11:29:11 -0700 Subject: [PATCH] Fix mktime/timegm for time_t > MAX_INT32 Fixes: #19694 --- src/library.js | 4 ++-- src/library_sigs.js | 4 ++-- system/lib/libc/emscripten_internal.h | 8 ++------ test/core/test_time.cpp | 14 +++++++------- test/core/test_time.out | 1 + 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/library.js b/src/library.js index b2b67a46dbff9..3e298b20ec2cf 100644 --- a/src/library.js +++ b/src/library.js @@ -476,7 +476,7 @@ mergeInto(LibraryManager.library, { {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getMonth()', 'i32') }}}; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getYear()', 'i32') }}}; - return (date.getTime() / 1000)|0; + return {{{ makeReturn64('date.getTime() / 1000') }}}; }, _gmtime_js__deps: ['$readI53FromI64'].concat(i53ConversionDeps), @@ -510,7 +510,7 @@ mergeInto(LibraryManager.library, { var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}}; - return (date.getTime() / 1000)|0; + return {{{ makeReturn64('date.getTime() / 1000') }}}; }, _localtime_js__deps: ['$readI53FromI64', '$ydayFromDate'].concat(i53ConversionDeps), diff --git a/src/library_sigs.js b/src/library_sigs.js index 16652976e3b06..099b34ba69162 100644 --- a/src/library_sigs.js +++ b/src/library_sigs.js @@ -353,12 +353,12 @@ sigs = { _emval_typeof__sig: 'pp', _gmtime_js__sig: 'vjp', _localtime_js__sig: 'vjp', - _mktime_js__sig: 'ip', + _mktime_js__sig: 'jp', _mmap_js__sig: 'ipiiijpp', _msync_js__sig: 'ippiiij', _munmap_js__sig: 'ippiiij', _setitimer_js__sig: 'iid', - _timegm_js__sig: 'ip', + _timegm_js__sig: 'jp', _tzset_js__sig: 'vppp', _wasmfs_copy_preloaded_file_data__sig: 'vip', _wasmfs_create_fetch_backend_js__sig: 'vp', diff --git a/system/lib/libc/emscripten_internal.h b/system/lib/libc/emscripten_internal.h index e2210561ab99d..c5cdfba107c25 100644 --- a/system/lib/libc/emscripten_internal.h +++ b/system/lib/libc/emscripten_internal.h @@ -35,12 +35,8 @@ void emscripten_memset_big(void* ptr, char value, size_t n); void emscripten_notify_memory_growth(size_t memory_index); -// Declare these functions `int` rather than time_t to avoid int64 at the wasm -// boundary (avoids 64-bit complexity at the boundary when WASM_BIGINT is -// missing). -// TODO(sbc): Covert back to `time_t` before 2038 ... -int _timegm_js(struct tm* tm); -int _mktime_js(struct tm* tm); +time_t _timegm_js(struct tm* tm); +time_t _mktime_js(struct tm* tm); void _localtime_js(time_t t, struct tm* __restrict__ tm); void _gmtime_js(time_t t, struct tm* __restrict__ tm); diff --git a/test/core/test_time.cpp b/test/core/test_time.cpp index feb34a7089f8d..642e08a833386 100644 --- a/test/core/test_time.cpp +++ b/test/core/test_time.cpp @@ -10,8 +10,7 @@ #include #include -void -check_gmtime_localtime(time_t time) +void check_gmtime_localtime(time_t time) { char gmbuf[32], locbuf[32]; const char fmt[] = "%Y-%m-%d %H:%M:%S"; @@ -46,7 +45,7 @@ int main() { tzset(); printf("tzname[0] set: %d\n", strlen(tzname[0]) >= 3); printf("tzname[1] set: %d\n", strlen(tzname[1]) >= 3); - + // Verify gmtime() creates correct struct. tm_ptr = gmtime(&xmas2002); printf("sec: %d\n", tm_ptr->tm_sec); @@ -60,7 +59,7 @@ int main() { printf("dst: %d\n", tm_ptr->tm_isdst); printf("off: %ld\n", (long)tm_ptr->tm_gmtoff); printf("zone: %s\n", tm_ptr->tm_zone); - + // Verify timegm() reverses gmtime; run through an entire year in half hours. int timegmOk = 1; for (int i = 0; i < 2*24*266; ++i) { @@ -75,14 +74,14 @@ int main() { timegmOk = 0; } printf("timegm <-> gmtime: %d\n", timegmOk); - + // Verify gmtime_r() doesn't clobber static data. time_t t1 = 0; struct tm tm1; gmtime_r(&t1, &tm1); printf("old year still: %d\n", tm_ptr->tm_year); printf("new year: %d\n", tm1.tm_year); - + // Verify localtime() picks up timezone data. struct tm tm_winter, tm_summer; if (localtime_r(&xmas2002, &tm_winter) != &tm_winter) printf("localtime_r failed\n"); @@ -152,7 +151,7 @@ int main() { tm2.tm_hour != tm_local.tm_hour || tm2.tm_mday != tm_local.tm_mday || tm2.tm_mon != tm_local.tm_mon || tm2.tm_year != tm_local.tm_year || tm2.tm_wday != tm_local.tm_wday || tm2.tm_yday != tm_local.tm_yday); - + printf("mktime parameter is equivalent to localtime return: %d\n", mktimeOk); // Verify that mktime is able to guess what the dst is. It might get it wrong @@ -249,6 +248,7 @@ int main() { check_gmtime_localtime(-2147483649); check_gmtime_localtime(253402300799); // end of year 9999 check_gmtime_localtime(-62135596800); // beginning of year 1 + check_gmtime_localtime(0x83d4d9a5); // some time in 2040 (time_t > MAX_INT32) // check that localtime sets tm_yday correctly whenever the day rolls over (issue #17635) // prior to being fixed, tm_yday did not increment correctly at epoch time 1049061599 (2003-03-31 00:00:00) in CET time diff --git a/test/core/test_time.out b/test/core/test_time.out index daa6bd254b370..d0768c67a23e1 100644 --- a/test/core/test_time.out +++ b/test/core/test_time.out @@ -58,4 +58,5 @@ time: -2147483648, gmtime: 1901-12-13 20:45:52 time: -2147483649, gmtime: 1901-12-13 20:45:51 time: 253402300799, gmtime: 9999-12-31 23:59:59 time: -62135596800, gmtime: 1-01-01 00:00:00 +time: 2211764645, gmtime: 2040-02-02 03:04:05 success