Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix BZ #18985 -- out of range data to strftime() causes a segfault
  • Loading branch information
Paul Pluzhnikov committed Sep 26, 2015
1 parent fa752c6 commit d36c75f
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
@@ -1,3 +1,11 @@
2015-09-26 Paul Pluzhnikov <ppluzhnikov@google.com>

[BZ #18985]
* time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check.
(__strftime_internal): Likewise.
* time/tst-strftime.c (do_bz18985): New test.
(do_test): Call it.

2015-09-26 Joseph Myers <joseph@codesourcery.com>

[BZ #18956]
Expand Down
2 changes: 1 addition & 1 deletion NEWS
Expand Up @@ -16,7 +16,7 @@ Version 2.23
18618, 18647, 18661, 18674, 18675, 18681, 18757, 18778, 18781, 18787,
18789, 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825, 18857,
18863, 18870, 18872, 18873, 18875, 18887, 18921, 18951, 18952, 18956,
18961, 18966, 18967, 18970, 18977, 18980, 18981, 19003.
18961, 18966, 18967, 18970, 18977, 18980, 18981, 18985, 19003.

* The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead.
Expand Down
20 changes: 13 additions & 7 deletions time/strftime_l.c
Expand Up @@ -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)))
Expand All @@ -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))
Expand Down Expand Up @@ -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)
Expand Down
52 changes: 51 additions & 1 deletion time/tst-strftime.c
Expand Up @@ -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;
Expand Down Expand Up @@ -104,7 +154,7 @@ do_test (void)
}
}

return result;
return result + do_bz18985 ();
}

#define TEST_FUNCTION do_test ()
Expand Down

0 comments on commit d36c75f

Please sign in to comment.