>Synopsis:      strptime segfaults if anything follows %Z in template
>Category:      library
>Environment:
        System      : OpenBSD 5.5
        Details     : OpenBSD 5.5 (GENERIC.MP) #0: Mon May  5 18:58:07 UTC 2014
                         
[email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP

        Architecture: OpenBSD.amd64
        Machine     : amd64
>Description:

valen% ./s
GMT ok
US/Pacific PST ok
[1]    1289 segmentation fault (core dumped)  ./s

>How-To-Repeat:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
        struct tm ilikebigsegfaults;
        char *where;

        setenv("TZ", "GMT", 1);
        where = strptime("GMT anything ok", "%Z anything ", &ilikebigsegfaults);
        if (where != NULL)
                fprintf(stderr, "GMT %s\n", where);
        else
                fprintf(stderr, "GMT not ok - NULL\n");

        setenv("TZ", "US/Pacific", 1);

        where = strptime("PST anything ok", "%Z anything ", &ilikebigsegfaults);
        if (where != NULL)
                fprintf(stderr, "US/Pacific PST %s\n", where);
        else
                fprintf(stderr, "US/Pacific PST not ok - NULL\n");

        where = strptime("UTC anything", "%Z anything", &ilikebigsegfaults);
        if (where == NULL)
                fprintf(stderr, "US/Pacific UTC ok - no match\n");

        setenv("TZ", "UTC", 1);
        where = strptime("UTC anything ok", "%Z anything ", &ilikebigsegfaults);
        if (where != NULL)
                fprintf(stderr, "UTC %s\n", where);
        else
                fprintf(stderr, "UTC not ok - NULL\n");

        where = strptime("not ok", "%Z", &ilikebigsegfaults);
        if (where == NULL)
                fprintf(stderr, "UTC neg ok\n");
        else
                fprintf(stderr, "UTC neg %s - should fail\n", where);

        exit(0);
}

>Fix:

Though there might be better ways, e.g. to make tzname contain the needful,
given that there might be other ways of naming UTC?

--- /usr/src/lib/libc/time/strptime.c.orig      Tue Jul  8 05:16:27 2014
+++ /usr/src/lib/libc/time/strptime.c   Tue Jul  8 05:32:23 2014
@@ -56,9 +56,8 @@
 #define FIELD_TM_YEAR  (1 << 4)
 
 static char gmt[] = { "GMT" };
-#ifdef TM_ZONE
 static char utc[] = { "UTC" };
-#endif
+
 /* RFC-822/RFC-2822 */
 static const char * const nast[5] = {
        "EST",    "CST",    "MST",    "PST",    "\0\0\0"
@@ -409,6 +408,15 @@
                                tm->TM_ZONE = gmt;
 #endif
                                bp += 3;
+                       } else if (strncmp((const char *)bp, utc, 3) == 0) {
+                               tm->tm_isdst = 0;
+#ifdef TM_GMTOFF
+                               tm->TM_GMTOFF = 0;
+#endif
+#ifdef TM_ZONE
+                               tm->TM_ZONE = utc;
+#endif
+                               bp += 3;
                        } else {
                                ep = _find_string(bp, &i,
                                                 (const char * const *)tzname,
@@ -421,8 +429,10 @@
 #ifdef TM_ZONE
                                        tm->TM_ZONE = tzname[i];
 #endif
+                                       bp = ep;
+                               } else {
+                                       return NULL;
                                }
-                               bp = ep;
                        }
                        continue;

Reply via email to