1
From d36c75fc0d44deec29635dd239b0fbd206ca49b7 Mon Sep 17 00:00:00 2001
2
From: Paul Pluzhnikov <ppluzhnikov@google.com>
3
Date: Sat, 26 Sep 2015 13:27:48 -0700
4
Subject: [PATCH] Fix BZ #18985 -- out of range data to strftime() causes a segfault
7
* time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check.
8
(__strftime_internal): Likewise.
9
* time/tst-strftime.c (do_bz18985): New test.
12
[Note: patch differs from upstream commit in that the entries in
13
the Changelog and NEWS were dropped to avoid patch conflicts. -- sbeattie]
15
time/strftime_l.c | 20 +++++++++++++-------
16
time/tst-strftime.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
17
2 files changed, 64 insertions(+), 8 deletions(-)
19
Index: b/time/strftime_l.c
20
===================================================================
21
--- a/time/strftime_l.c
22
+++ b/time/strftime_l.c
23
@@ -513,13 +513,17 @@ __strftime_internal (s, maxsize, format,
24
only a few elements. Dereference the pointers only if the format
25
requires this. Then it is ok to fail if the pointers are invalid. */
27
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
28
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
29
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
31
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
32
+ ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
33
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
35
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
36
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
37
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
39
- ((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
40
+ ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
41
+ ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
43
((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
44
? NLW(PM_STR) : NLW(AM_STR)))
45
@@ -529,8 +533,10 @@ __strftime_internal (s, maxsize, format,
46
# define ap_len STRLEN (ampm)
49
-# define f_wkday (weekday_name[tp->tm_wday])
50
-# define f_month (month_name[tp->tm_mon])
51
+# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \
52
+ ? "?" : weekday_name[tp->tm_wday])
53
+# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \
54
+ ? "?" : month_name[tp->tm_mon])
55
# define a_wkday f_wkday
56
# define a_month f_month
57
# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
58
@@ -1324,7 +1330,7 @@ __strftime_internal (s, maxsize, format,
62
- zone = tzname[tp->tm_isdst];
63
+ zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
67
Index: b/time/tst-strftime.c
68
===================================================================
69
--- a/time/tst-strftime.c
70
+++ b/time/tst-strftime.c
82
+ memset (&ttm, 1, sizeof (ttm));
83
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
84
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
88
+ const char expected[]
89
+ = "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?";
90
+ if (0 != strcmp (buf, expected))
92
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
98
+ printf ("expected 66, got %d\n", rc);
102
+ /* Check negative values as well. */
103
+ memset (&ttm, 0xFF, sizeof (ttm));
104
+ ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
105
+ rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
109
+ const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 ";
110
+ if (0 != strcmp (buf, expected))
112
+ printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
118
+ printf ("expected 30, got %d\n", rc);
128
@@ -104,7 +154,7 @@ do_test (void)
133
+ return result + do_bz18985 ();
136
#define TEST_FUNCTION do_test ()