Skip to content

Fix mktime/timegm for time_t > MAX_INT32 #19700

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
4 changes: 2 additions & 2 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
8 changes: 2 additions & 6 deletions system/lib/libc/emscripten_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
14 changes: 7 additions & 7 deletions test/core/test_time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
#include <assert.h>
#include <math.h>

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";
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions test/core/test_time.out
Original file line number Diff line number Diff line change
Expand Up @@ -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