Skip to content

Commit

Permalink
msvcrt: Adjust _gmtime64_s() accepted time limits.
Browse files Browse the repository at this point in the history
CW-Bug-Id: #23111
  • Loading branch information
Paul Gofman committed Dec 9, 2023
1 parent cadbcbc commit cd80996
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
57 changes: 57 additions & 0 deletions dlls/msvcrt/tests/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
static struct tm* (__cdecl *p_gmtime)(time_t*);
static errno_t (__cdecl *p_gmtime32_s)(struct tm*, __time32_t*);
static struct tm* (__cdecl *p_gmtime64)(__time64_t*);
static errno_t (__cdecl *p_gmtime64_s)(struct tm*, __time64_t*);
static errno_t (__cdecl *p_strtime_s)(char*,size_t);
static errno_t (__cdecl *p_strdate_s)(char*,size_t);
static errno_t (__cdecl *p_localtime32_s)(struct tm*, __time32_t*);
Expand All @@ -76,6 +78,8 @@ static void init(void)
p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
p_gmtime = (void*)GetProcAddress(hmod, "gmtime");
p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
p_gmtime64 = (void*)GetProcAddress(hmod, "_gmtime64");
p_gmtime64_s = (void*)GetProcAddress(hmod, "_gmtime64_s");
p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
Expand Down Expand Up @@ -208,6 +212,58 @@ static void test_gmtime(void)
}
}

static void test_gmtime64(void)
{
struct tm *ptm, tm;
__time64_t t;
int ret;

t = -1;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 69 && tm.tm_hour == 23 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);

t = -43200;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 69 && tm.tm_hour == 12 && tm.tm_min == 0 && tm.tm_sec == 0, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);

t = -43201;
ptm = p_gmtime64(&t);
ok(!ptm, "got non-NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime64_s(&tm, &t);
ok(ret == EINVAL, "got %d.\n", ret);
ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);

t = _MAX__TIME64_T + 46800;
memset(&tm, 0xcc, sizeof(tm));
ptm = p_gmtime64(&t);
ok(!!ptm, "got NULL.\n");
ret = p_gmtime64_s(&tm, &t);
ok(!ret, "got %d.\n", ret);
ok(tm.tm_year == 1101 && tm.tm_hour == 20 && tm.tm_min == 59 && tm.tm_sec == 59, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);

t = _MAX__TIME64_T + 46801;
ptm = p_gmtime64(&t);
ok(!ptm, "got non-NULL.\n");
memset(&tm, 0xcc, sizeof(tm));
ret = p_gmtime64_s(&tm, &t);
ok(ret == EINVAL, "got %d.\n", ret);
ok(tm.tm_year == -1 && tm.tm_hour == -1 && tm.tm_min == -1 && tm.tm_sec == -1, "got %d, %d, %d, %d.\n",
tm.tm_year, tm.tm_hour, tm.tm_min, tm.tm_sec);
}

static void test_mktime(void)
{
TIME_ZONE_INFORMATION tzinfo;
Expand Down Expand Up @@ -960,6 +1016,7 @@ START_TEST(time)
test_strftime();
test_ctime();
test_gmtime();
test_gmtime64();
test_mktime();
test_localtime();
test_strdate();
Expand Down
18 changes: 17 additions & 1 deletion dlls/msvcrt/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
WINE_DECLARE_DEBUG_CHANNEL(time);

#undef _ctime32
#undef _difftime32
Expand Down Expand Up @@ -457,7 +458,7 @@ int CDECL _gmtime64_s(struct tm *res, const __time64_t *secs)
SYSTEMTIME st;
ULONGLONG time;

if (!res || !secs || *secs < 0 || *secs > _MAX__TIME64_T) {
if (!res || !secs || *secs < -43200 || *secs > _MAX__TIME64_T + 46800) {
if (res) {
write_invalid_msvcrt_tm(res);
}
Expand Down Expand Up @@ -497,6 +498,8 @@ struct tm* CDECL _gmtime64(const __time64_t *secs)
{
thread_data_t * const data = msvcrt_get_thread_data();

TRACE_(time)("secs %p, %I64d.\n", secs, secs ? *secs : 0);

if(!data->time_buffer)
data->time_buffer = malloc(sizeof(struct tm));

Expand All @@ -513,6 +516,13 @@ int CDECL _gmtime32_s(struct tm *res, const __time32_t *secs)
__time64_t secs64;

if(secs) {
if (*secs < 0)
{
if (res)
write_invalid_msvcrt_tm(res);
*_errno() = EINVAL;
return EINVAL;
}
secs64 = *secs;
return _gmtime64_s(res, &secs64);
}
Expand All @@ -529,6 +539,12 @@ struct tm* CDECL _gmtime32(const __time32_t* secs)
if(!secs)
return NULL;

if (*secs < 0)
{
*_errno() = EINVAL;
return NULL;
}

secs64 = *secs;
return _gmtime64( &secs64 );
}
Expand Down

0 comments on commit cd80996

Please sign in to comment.