| commit d36c75fc0d44deec29635dd239b0fbd206ca49b7 |
| Author: Paul Pluzhnikov <ppluzhnikov@google.com> |
| Date: Sat Sep 26 13:27:48 2015 -0700 |
| |
| Fix BZ #18985 -- out of range data to strftime() causes a segfault |
| |
| diff --git a/time/strftime_l.c b/time/strftime_l.c |
| index b48ef34..4eb647c 100644 |
| |
| |
| @@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| only a few elements. Dereference the pointers only if the format |
| requires this. Then it is ok to fail if the pointers are invalid. */ |
| # define a_wkday \ |
| - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)) |
| + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ |
| + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))) |
| # define f_wkday \ |
| - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)) |
| + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ |
| + ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))) |
| # define a_month \ |
| - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)) |
| + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ |
| + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))) |
| # define f_month \ |
| - ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)) |
| + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ |
| + ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) |
| # define ampm \ |
| ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ |
| ? NLW(PM_STR) : NLW(AM_STR))) |
| @@ -526,8 +530,10 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| # define ap_len STRLEN (ampm) |
| #else |
| # if !HAVE_STRFTIME |
| -# define f_wkday (weekday_name[tp->tm_wday]) |
| -# define f_month (month_name[tp->tm_mon]) |
| +# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \ |
| + ? "?" : weekday_name[tp->tm_wday]) |
| +# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \ |
| + ? "?" : month_name[tp->tm_mon]) |
| # define a_wkday f_wkday |
| # define a_month f_month |
| # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) |
| @@ -1321,7 +1327,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument |
| *tzset_called = true; |
| } |
| # endif |
| - zone = tzname[tp->tm_isdst]; |
| + zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; |
| } |
| #endif |
| if (! zone) |
| diff --git a/time/tst-strftime.c b/time/tst-strftime.c |
| index 374fba4..af3ff72 100644 |
| |
| |
| @@ -4,6 +4,56 @@ |
| #include <time.h> |
| |
| |
| +static int |
| +do_bz18985 (void) |
| +{ |
| + char buf[1000]; |
| + struct tm ttm; |
| + int rc, ret = 0; |
| + |
| + memset (&ttm, 1, sizeof (ttm)); |
| + ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ |
| + rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); |
| + |
| + if (rc == 66) |
| + { |
| + const char expected[] |
| + = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?"; |
| + if (0 != strcmp (buf, expected)) |
| + { |
| + printf ("expected:\n %s\ngot:\n %s\n", expected, buf); |
| + ret += 1; |
| + } |
| + } |
| + else |
| + { |
| + printf ("expected 66, got %d\n", rc); |
| + ret += 1; |
| + } |
| + |
| + /* Check negative values as well. */ |
| + memset (&ttm, 0xFF, sizeof (ttm)); |
| + ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */ |
| + rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm); |
| + |
| + if (rc == 30) |
| + { |
| + const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 "; |
| + if (0 != strcmp (buf, expected)) |
| + { |
| + printf ("expected:\n %s\ngot:\n %s\n", expected, buf); |
| + ret += 1; |
| + } |
| + } |
| + else |
| + { |
| + printf ("expected 30, got %d\n", rc); |
| + ret += 1; |
| + } |
| + |
| + return ret; |
| +} |
| + |
| static struct |
| { |
| const char *fmt; |
| @@ -104,7 +154,7 @@ do_test (void) |
| } |
| } |
| |
| - return result; |
| + return result + do_bz18985 (); |
| } |
| |
| #define TEST_FUNCTION do_test () |