fix parsing offsets after long timezone names
authorSamuel Holland <samuel@sholland.org>
Sat, 22 Feb 2020 22:01:13 +0000 (16:01 -0600)
committerRich Felker <dalias@aerifal.cx>
Sat, 21 Mar 2020 16:47:09 +0000 (12:47 -0400)
TZ containg a timezone name with >TZNAME_MAX characters currently
breaks musl's timezone parsing. getname() stops after TZNAME_MAX
characters. getoff() will consume no characters (because the next
character is not a digit) and incorrectly return 0. Then, because
there are remaining alphabetic characters, __daylight == 1, and
dst_off == -3600.

getname() must consume the entire timezone name, even if it will not
fit in d/__tzname, so when it returns, s points to the offset digits.

src/time/__tz.c

index a962960e9baa30b1c7924dc0a8cc0eb2454dfb66..49a7371ebc15bb140c5f153c8ba35726e60675e7 100644 (file)
@@ -86,15 +86,15 @@ static void getname(char *d, const char **p)
        int i;
        if (**p == '<') {
                ++*p;
-               for (i=0; (*p)[i] && (*p)[i]!='>' && i<TZNAME_MAX; i++)
-                       d[i] = (*p)[i];
+               for (i=0; (*p)[i] && (*p)[i]!='>'; i++)
+                       if (i<TZNAME_MAX) d[i] = (*p)[i];
                if ((*p)[i]) ++*p;
        } else {
-               for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
-                       d[i] = (*p)[i];
+               for (i=0; ((*p)[i]|32)-'a'<26U; i++)
+                       if (i<TZNAME_MAX) d[i] = (*p)[i];
        }
        *p += i;
-       d[i] = 0;
+       d[i<TZNAME_MAX?i:TZNAME_MAX] = 0;
 }
 
 #define VEC(...) ((const unsigned char[]){__VA_ARGS__})