Fix strftime if tm_zone is null.
Upstream tzcode said "On platforms with tm_zone, strftime.c now assumes it is not NULL". Which is fine for any struct tm generated by tzcode, but not necessarily true of a struct tm constructed by arbitrary code. In particular, Netflix on Nexus Player was failing to start because they format "%Z" with a struct tm whose tm_zone is null (the other fields are valid, but, yeah, that's probably not intentional). glibc takes a null tm_zone to mean "the current time zone", so let's do that too. (Historically Android would use the empty string, and POSIX doesn't clarify which of this is the appropriate behavior when tm_zone is null.) Bug: http://b/25170306 Change-Id: Idbf68bfe90d143aca7dada8607742905188b1d33
This commit is contained in:
parent
7c10ee9473
commit
a9cac4c87a
@ -725,6 +725,7 @@ LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
LOCAL_CFLAGS += -DALL_STATE
|
||||
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
|
||||
LOCAL_CFLAGS += -DSTD_INSPIRED
|
||||
# Obviously, we want to be thread-safe.
|
||||
LOCAL_CFLAGS += -DTHREAD_SAFE
|
||||
# The name of the tm_gmtoff field in our struct tm.
|
||||
LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
|
||||
@ -732,6 +733,8 @@ LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
|
||||
LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
|
||||
# Include timezone and daylight globals.
|
||||
LOCAL_CFLAGS += -DUSG_COMPAT=1
|
||||
# Use the empty string (instead of " ") as the timezone abbreviation fallback.
|
||||
LOCAL_CFLAGS += -DWILDABBR=\"\"
|
||||
LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
|
||||
LOCAL_CFLAGS += -Dlint
|
||||
|
||||
|
@ -502,7 +502,23 @@ label:
|
||||
continue;
|
||||
case 'Z':
|
||||
#ifdef TM_ZONE
|
||||
pt = _add(t->TM_ZONE, pt, ptlim, modifier);
|
||||
// BEGIN: Android-changed.
|
||||
{
|
||||
const char* zone = t->TM_ZONE;
|
||||
if (!zone || !*zone) {
|
||||
// "The value of tm_isdst shall be positive if Daylight Savings Time is
|
||||
// in effect, 0 if Daylight Savings Time is not in effect, and negative
|
||||
// if the information is not available."
|
||||
if (t->tm_isdst == 0) zone = tzname[0];
|
||||
else if (t->tm_isdst > 0) zone = tzname[1];
|
||||
|
||||
// "Replaced by the timezone name or abbreviation, or by no bytes if no
|
||||
// timezone information exists."
|
||||
if (!zone || !*zone) zone = "";
|
||||
}
|
||||
pt = _add(zone, pt, ptlim, modifier);
|
||||
}
|
||||
// END: Android-changed.
|
||||
#else
|
||||
if (t->tm_isdst >= 0)
|
||||
pt = _add(tzname[t->tm_isdst != 0],
|
||||
|
@ -143,6 +143,44 @@ TEST(time, strftime) {
|
||||
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
|
||||
}
|
||||
|
||||
TEST(time, strftime_null_tm_zone) {
|
||||
// Netflix on Nexus Player wouldn't start (http://b/25170306).
|
||||
struct tm t;
|
||||
memset(&t, 0, sizeof(tm));
|
||||
|
||||
char buf[64];
|
||||
|
||||
setenv("TZ", "America/Los_Angeles", 1);
|
||||
tzset();
|
||||
|
||||
t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
|
||||
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
|
||||
EXPECT_STREQ("<PST>", buf);
|
||||
|
||||
#if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
|
||||
t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
|
||||
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
|
||||
EXPECT_STREQ("<PDT>", buf);
|
||||
|
||||
t.tm_isdst = -123; // "and negative if the information is not available".
|
||||
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
|
||||
EXPECT_STREQ("<>", buf);
|
||||
#endif
|
||||
|
||||
setenv("TZ", "UTC", 1);
|
||||
tzset();
|
||||
|
||||
t.tm_isdst = 0;
|
||||
EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
|
||||
EXPECT_STREQ("<UTC>", buf);
|
||||
|
||||
#if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
|
||||
t.tm_isdst = 1; // UTC has no DST.
|
||||
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
|
||||
EXPECT_STREQ("<>", buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(time, strptime) {
|
||||
setenv("TZ", "UTC", 1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user