From f0c223df7b10491e7690a33f1bf2283885954060 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Sun, 17 Jul 2022 22:45:36 -0700 Subject: [PATCH] Fix utime/stat for time_t > 2^32 See: #17393 --- src/library_syscall.js | 13 +++++---- src/parseTools.js | 4 +++ .../libc/musl/arch/emscripten/bits/alltypes.h | 2 +- tests/stat/test_stat.c | 29 ++++++++++--------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/library_syscall.js b/src/library_syscall.js index ed7f97d230fdf..3357376c9c8c9 100644 --- a/src/library_syscall.js +++ b/src/library_syscall.js @@ -64,12 +64,12 @@ var SyscallsLibrary = { {{{ makeSetValue('buf', C_STRUCTS.stat.st_size, 'stat.size', 'i64') }}}; {{{ makeSetValue('buf', C_STRUCTS.stat.st_blksize, '4096', 'i32') }}}; {{{ makeSetValue('buf', C_STRUCTS.stat.st_blocks, 'stat.blocks', 'i32') }}}; - {{{ makeSetValue('buf', C_STRUCTS.stat.st_atim.tv_sec, '(stat.atime.getTime() / 1000)|0', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_atim.tv_sec, '(stat.atime.getTime() / 1000)|0 ', 'i64') }}}; {{{ makeSetValue('buf', C_STRUCTS.stat.st_atim.tv_nsec, '0', 'i32') }}}; - {{{ makeSetValue('buf', C_STRUCTS.stat.st_mtim.tv_sec, '(stat.mtime.getTime() / 1000)|0', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_mtim.tv_sec, '(stat.mtime.getTime() / 1000)|0', 'i64') }}}; {{{ makeSetValue('buf', C_STRUCTS.stat.st_mtim.tv_nsec, '0', 'i32') }}}; - {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_sec, '(stat.ctime.getTime() / 1000)|0', 'i32') }}}; - {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_nsec, '0', 'i32') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_sec, '(stat.ctime.getTime() / 1000)|0', 'i64') }}}; + {{{ makeSetValue('buf', C_STRUCTS.stat.st_ctim.tv_nsec, '0', 'i64') }}}; {{{ makeSetValue('buf', C_STRUCTS.stat.st_ino, 'stat.ino', 'i64') }}}; return 0; }, @@ -955,6 +955,7 @@ var SyscallsLibrary = { return 0; }, __syscall_utimensat__sig: 'iippi', + __syscall_utimensat__deps: ['$readI53FromU64'], __syscall_utimensat: function(dirfd, path, times, flags) { path = SYSCALLS.getStr(path); #if ASSERTIONS @@ -965,11 +966,11 @@ var SyscallsLibrary = { var atime = Date.now(); var mtime = atime; } else { - var seconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_sec, 'i32') }}}; + var seconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_sec, 'i53') }}}; var nanoseconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_nsec, 'i32') }}}; atime = (seconds*1000) + (nanoseconds/(1000*1000)); times += {{{ C_STRUCTS.timespec.__size__ }}}; - seconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_sec, 'i32') }}}; + seconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_sec, 'i53') }}}; nanoseconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_nsec, 'i32') }}}; mtime = (seconds*1000) + (nanoseconds/(1000*1000)); } diff --git a/src/parseTools.js b/src/parseTools.js index 5b6952fa43e3b..4a340d92803d7 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -407,7 +407,11 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align) { } } + const offset = calcFastOffset(ptr, pos, noNeedFirst); + if (type == 'i53') { + return 'readI53FromU64(' + offset + ')'; + } const slab = getHeapForType(type); let ret = slab + '[' + getHeapOffset(offset, type) + ']'; diff --git a/system/lib/libc/musl/arch/emscripten/bits/alltypes.h b/system/lib/libc/musl/arch/emscripten/bits/alltypes.h index 1f7a6718233bc..eae056d4a4460 100644 --- a/system/lib/libc/musl/arch/emscripten/bits/alltypes.h +++ b/system/lib/libc/musl/arch/emscripten/bits/alltypes.h @@ -309,7 +309,7 @@ struct timeval { time_t tv_sec; suseconds_t tv_usec; }; #endif #if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) -struct timespec { time_t tv_sec; long tv_nsec; }; +struct timespec { time_t tv_sec; int tv_nsec; }; #define __DEFINED_struct_timespec #endif diff --git a/tests/stat/test_stat.c b/tests/stat/test_stat.c index 7d05b929d73a4..d785b5e25efc6 100644 --- a/tests/stat/test_stat.c +++ b/tests/stat/test_stat.c @@ -30,8 +30,9 @@ void create_file(const char *path, const char *buffer, int mode) { close(fd); } +#define TEST_TIME (1ll << 34) void setup() { - struct utimbuf t = {1200000000, 1200000000}; + struct utimbuf t = {TEST_TIME, TEST_TIME}; mkdir("folder", 0777); create_file("folder/file", "abcdef", 0777); @@ -51,7 +52,7 @@ void cleanup() { void test() { int err; struct stat s; - struct utimbuf t = {1200000000, 1200000000}; + struct utimbuf t = {TEST_TIME, TEST_TIME}; // non-existent err = stat("does_not_exist", &s); @@ -70,8 +71,8 @@ void test() { assert(s.st_rdev == 0); #endif assert(s.st_size); - assert(s.st_atime == 1200000000); - assert(s.st_mtime == 1200000000); + assert(s.st_atime == TEST_TIME); + assert(s.st_mtime == TEST_TIME); assert(s.st_ctime); #ifdef __EMSCRIPTEN__ assert(s.st_blksize == 4096); @@ -92,8 +93,8 @@ void test() { assert(s.st_nlink); assert(s.st_rdev == 0); assert(s.st_size == 6); - assert(s.st_atime == 1200000000); - assert(s.st_mtime == 1200000000); + assert(s.st_atime == TEST_TIME); + assert(s.st_mtime == TEST_TIME); assert(s.st_ctime); #ifdef __EMSCRIPTEN__ assert(s.st_blksize == 4096); @@ -110,8 +111,8 @@ void test() { assert(s.st_nlink); assert(s.st_rdev == 0); assert(s.st_size == 6); - assert(s.st_atime == 1200000000); - assert(s.st_mtime == 1200000000); + assert(s.st_atime == TEST_TIME); + assert(s.st_mtime == TEST_TIME); assert(s.st_ctime); #ifdef __EMSCRIPTEN__ assert(s.st_blksize == 4096); @@ -152,8 +153,8 @@ void test() { assert(s.st_nlink); assert(s.st_rdev == 0); assert(s.st_size == 6); - assert(s.st_atime == 1200000000); - assert(s.st_mtime == 1200000000); + assert(s.st_atime == TEST_TIME); + assert(s.st_mtime == TEST_TIME); assert(s.st_ctime); #ifdef __EMSCRIPTEN__ assert(s.st_blksize == 4096); @@ -170,8 +171,8 @@ void test() { assert(s.st_nlink); assert(s.st_rdev == 0); assert(s.st_size == 4); // strlen("file") - assert(s.st_atime != 1200000000); // should NOT match the utime call we did for dir/file - assert(s.st_mtime != 1200000000); + assert(s.st_atime != TEST_TIME); // should NOT match the utime call we did for dir/file + assert(s.st_mtime != TEST_TIME); assert(s.st_ctime); #ifdef __EMSCRIPTEN__ assert(s.st_blksize == 4096); @@ -183,11 +184,11 @@ void test() { utime("folder/subdir", &t); create_file("folder/subdir/file", "abcdef", 0777); err = stat("folder/subdir", &s); - assert(s.st_mtime != 1200000000); + assert(s.st_mtime != TEST_TIME); utime("folder/subdir", &t); unlink("folder/subdir/file"); err = stat("folder/subdir", &s); - assert(s.st_mtime != 1200000000); + assert(s.st_mtime != TEST_TIME); puts("success"); }