From 937822abb6ac48880939be3c60e6b57bddf62cf6 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 23 Jun 2021 17:22:47 -0400 Subject: fix TZ parsing logic for identifying POSIX-form strings previously, the contents of the TZ variable were considered a candidate for a file/path name only if they began with a colon or contained a slash before any comma. the latter was very sloppy logic to avoid treating any valid POSIX TZ string as a file name, but it also triggered on values that are not valid POSIX TZ strings, including 3-letter timezone names without any offset. instead, only treat the TZ variable as POSIX form if it begins with a nonzero standard time name followed by +, -, or a digit. also, special case GMT and UTC to always be treated as POSIX form (with implicit zero offset) so that a stray file by the same name cannot break software that depends on setting TZ=GMT or TZ=UTC. --- src/time/__tz.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/time/__tz.c b/src/time/__tz.c index 09a6317e..3e2fcdcb 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "libc.h" #include "lock.h" #include "fork_impl.h" @@ -154,10 +155,21 @@ static void do_tzset() } if (old_tz) memcpy(old_tz, s, i+1); + int posix_form = 0; + if (*s != ':') { + p = s; + char dummy_name[TZNAME_MAX+1]; + getname(dummy_name, &p); + if (p!=s && (*p == '+' || *p == '-' || isdigit(*p) + || !strcmp(dummy_name, "UTC") + || !strcmp(dummy_name, "GMT"))) + posix_form = 1; + } + /* Non-suid can use an absolute tzfile pathname or a relative * pathame beginning with "."; in secure mode, only the * standard path will be searched. */ - if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { + if (!posix_form) { if (*s == ':') s++; if (*s == '/' || *s == '.') { if (!libc.secure || !strcmp(s, "/etc/localtime")) -- cgit v1.2.1