From 154e2026c83575eb17101df3a8d1192e305588d4 Mon Sep 17 00:00:00 2001 From: Satoru Takeuchi Date: Tue, 27 May 2014 17:04:04 +0900 Subject: [PATCH] libc: Fix mktime returns an uncorrect time in empty TZ case The mktime API returned an uncorrect time when TZ is set as empty. A timezone UTC/GMT+0 should be implied in the empty case. However mktime keeps previous information about timezone. If mktime was called with a timezone which has DST before, the "defaulttype" member of "state" structure wouldn't be 0. Then it would be used next time, even though UTC/GMT+0 doesn't have DST. Added initialization of the "defaulttype" in the empty TZ case. Change-Id: Ic480c63c548c05444134e0aefb30a7b380e3f40b --- libc/tzcode/localtime.c | 1 + tests/time_test.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 28d13f417..29f605c08 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -1257,6 +1257,7 @@ tzset_locked(void) lclptr->ttis[0].tt_gmtoff = 0; lclptr->ttis[0].tt_abbrind = 0; (void) strcpy(lclptr->chars, gmt); + lclptr->defaulttype = 0; } else if (tzload(name, lclptr, TRUE) != 0) if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) (void) gmtload(lclptr); diff --git a/tests/time_test.cpp b/tests/time_test.cpp index 7a551b42a..e0231b1ca 100644 --- a/tests/time_test.cpp +++ b/tests/time_test.cpp @@ -71,6 +71,30 @@ TEST(time, gmtime_no_stack_overflow_14313703) { ASSERT_EQ(0, pthread_join(t, &result)); } +TEST(time, mktime_empty_TZ) { + // tzcode used to have a bug where it didn't reinitialize some internal state. + + // Choose a time where DST is set. + struct tm t; + memset(&t, 0, sizeof(tm)); + t.tm_year = 1980 - 1900; + t.tm_mon = 6; + t.tm_mday = 2; + + setenv("TZ", "America/Los_Angeles", 1); + tzset(); + ASSERT_EQ(static_cast(331372800U), mktime(&t)); + + memset(&t, 0, sizeof(tm)); + t.tm_year = 1980 - 1900; + t.tm_mon = 6; + t.tm_mday = 2; + + setenv("TZ", "", 1); // Implies UTC. + tzset(); + ASSERT_EQ(static_cast(331344000U), mktime(&t)); +} + TEST(time, mktime_10310929) { struct tm t; memset(&t, 0, sizeof(tm)); -- 2.11.0