summaryrefslogtreecommitdiff
path: root/src/time/__tz.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2021-06-23 17:22:47 -0400
committerRich Felker <dalias@aerifal.cx>2021-06-23 17:30:10 -0400
commit937822abb6ac48880939be3c60e6b57bddf62cf6 (patch)
tree0160a87a71cb0a5b005519a9e6219837aa6a4a53 /src/time/__tz.c
parent1f0c7cb1cc2170bf230623dc0b57d9a9f001af08 (diff)
downloadmusl-937822abb6ac48880939be3c60e6b57bddf62cf6.tar.gz
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.
Diffstat (limited to 'src/time/__tz.c')
-rw-r--r--src/time/__tz.c14
1 files changed, 13 insertions, 1 deletions
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 <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <ctype.h>
#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"))