Erich E. Hoover : ntdll: Fix converting large 32-bit time_t when time_t is signed.

Alexandre Julliard julliard at winehq.org
Tue Nov 24 17:01:44 CST 2020


Module: wine
Branch: master
Commit: 773b97bb2b0f4421d213b466337dd6d66b2b0856
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=773b97bb2b0f4421d213b466337dd6d66b2b0856

Author: Erich E. Hoover <erich.e.hoover at gmail.com>
Date:   Sat Nov 21 22:33:20 2020 -0700

ntdll: Fix converting large 32-bit time_t when time_t is signed.

Signed-off-by: Erich E. Hoover <erich.e.hoover at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/tests/file.c        | 12 ++++++++++++
 dlls/ntdll/unix/file.c         | 10 +++++-----
 dlls/ntdll/unix/sync.c         | 12 +++++-------
 dlls/ntdll/unix/unix_private.h |  9 ++++++++-
 4 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 8b9ec4f624d..2507437c8c3 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -1361,6 +1361,18 @@ static void test_file_basic_information(void)
     ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
     ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
 
+    memset(&fbi2, 0, sizeof(fbi2));
+    fbi2.LastAccessTime.QuadPart = 0x200deadcafebeef;
+    U(io).Status = 0xdeadbeef;
+    res = pNtSetInformationFile(h, &io, &fbi2, sizeof(fbi2), FileBasicInformation);
+    ok ( res == STATUS_SUCCESS, "can't set system attribute, NtSetInformationFile returned %x\n", res );
+    ok ( U(io).Status == STATUS_SUCCESS, "can't set system attribute, io.Status is %x\n", U(io).Status );
+    res = pNtQueryInformationFile(h, &io, &fbi, sizeof(fbi), FileBasicInformation);
+    ok ( res == STATUS_SUCCESS, "can't get system attribute, NtQueryInformationFile returned %x\n", res );
+    ok ( U(io).Status == STATUS_SUCCESS, "can't get system attribute, io.Status is %x\n", U(io).Status );
+    ok ( fbi2.LastAccessTime.QuadPart == fbi.LastAccessTime.QuadPart,
+         "large access time set/get does not match.\n" );
+
     memset(&fbi2, 0, sizeof(fbi2));
     res = pNtQueryInformationFile(h, &io, &fbi2, sizeof fbi2, FileBasicInformation);
     ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index cf413f46e5c..6d6edfe8926 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -1631,9 +1631,9 @@ static NTSTATUS set_file_times( int fd, const LARGE_INTEGER *mtime, const LARGE_
 static inline void get_file_times( const struct stat *st, LARGE_INTEGER *mtime, LARGE_INTEGER *ctime,
                                    LARGE_INTEGER *atime, LARGE_INTEGER *creation )
 {
-    mtime->QuadPart = st->st_mtime * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
-    ctime->QuadPart = st->st_ctime * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
-    atime->QuadPart = st->st_atime * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
+    mtime->QuadPart = ticks_from_time_t( st->st_mtime );
+    ctime->QuadPart = ticks_from_time_t( st->st_ctime );
+    atime->QuadPart = ticks_from_time_t( st->st_atime );
 #ifdef HAVE_STRUCT_STAT_ST_MTIM
     mtime->QuadPart += st->st_mtim.tv_nsec / 100;
 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
@@ -1650,14 +1650,14 @@ static inline void get_file_times( const struct stat *st, LARGE_INTEGER *mtime,
     atime->QuadPart += st->st_atimespec.tv_nsec / 100;
 #endif
 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
-    creation->QuadPart = st->st_birthtime * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
+    creation->QuadPart = ticks_from_time_t( st->st_birthtime );
 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIM
     creation->QuadPart += st->st_birthtim.tv_nsec / 100;
 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
     creation->QuadPart += st->st_birthtimespec.tv_nsec / 100;
 #endif
 #elif defined(HAVE_STRUCT_STAT___ST_BIRTHTIME)
-    creation->QuadPart = st->__st_birthtime * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
+    creation->QuadPart = ticks_from_time_t( st->__st_birthtime );
 #ifdef HAVE_STRUCT_STAT___ST_BIRTHTIM
     creation->QuadPart += st->__st_birthtim.tv_nsec / 100;
 #endif
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index bba7af7e34f..dcc8c5447ef 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -104,7 +104,7 @@ static inline ULONGLONG monotonic_counter(void)
         return ts.tv_sec * (ULONGLONG)TICKSPERSEC + ts.tv_nsec / 100;
 #endif
     gettimeofday( &now, 0 );
-    return now.tv_sec * (ULONGLONG)TICKSPERSEC + now.tv_usec * 10 + TICKS_1601_TO_1970 - server_start_time;
+    return ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10 - server_start_time;
 }
 
 
@@ -1392,8 +1392,7 @@ NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time )
 
     if (!clock_gettime( clock_id, &ts ))
     {
-        time->QuadPart = ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
-        time->QuadPart += (ts.tv_nsec + 50) / 100;
+        time->QuadPart = ticks_from_time_t( ts.tv_sec ) + (ts.tv_nsec + 50) / 100;
     }
     else
 #endif /* HAVE_CLOCK_GETTIME */
@@ -1401,8 +1400,7 @@ NTSTATUS WINAPI NtQuerySystemTime( LARGE_INTEGER *time )
         struct timeval now;
 
         gettimeofday( &now, 0 );
-        time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
-        time->QuadPart += now.tv_usec * 10;
+        time->QuadPart = ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10;
     }
     return STATUS_SUCCESS;
 }
@@ -1475,10 +1473,10 @@ LONGLONG WINAPI RtlGetSystemTimePrecise(void)
     struct timespec ts;
 
     if (!clock_gettime( CLOCK_REALTIME, &ts ))
-        return ts.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970 + (ts.tv_nsec + 50) / 100;
+        return ticks_from_time_t( ts.tv_sec ) + (ts.tv_nsec + 50) / 100;
 #endif
     gettimeofday( &now, 0 );
-    return now.tv_sec * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970 + now.tv_usec * 10;
+    return ticks_from_time_t( now.tv_sec ) + now.tv_usec * 10;
 }
 
 
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index c3ad0a41098..23731f0fdc6 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -249,7 +249,14 @@ extern void WINAPI DECLSPEC_NORETURN call_raise_user_exception_dispatcher( NTSTA
 
 #define TICKSPERSEC 10000000
 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)86400)
-#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
+
+static inline ULONGLONG ticks_from_time_t( time_t time )
+{
+    if (sizeof(time_t) == sizeof(int))  /* time_t may be signed */
+        return ((ULONGLONG)(ULONG)time + SECS_1601_TO_1970) * TICKSPERSEC;
+    else
+        return ((ULONGLONG)time + SECS_1601_TO_1970) * TICKSPERSEC;
+}
 
 static inline const char *debugstr_us( const UNICODE_STRING *us )
 {




More information about the wine-cvs mailing list