1From 45f051239312e43bd4f92b9339fe67c6798a0321 Mon Sep 17 00:00:00 2001
2From: Balazs Scheidler <bazsi77@gmail.com>
3Date: Sat, 20 Aug 2022 12:43:42 +0200
4Subject: [PATCH 5/8] timeutils: add tests for non-zero terminated inputs
5
6CVE: CVE-2022-38725
7
8Upstream-Status: Backport
9[https://github.com/syslog-ng/syslog-ng/commit/45f051239312e43bd4f92b9339fe67c6798a0321]
10
11Signed-off-by: Balazs Scheidler <bazsi77@gmail.com>
12
13Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
14---
15 lib/timeutils/tests/test_scan-timestamp.c | 126 +++++++++++++++++++---
16 1 file changed, 113 insertions(+), 13 deletions(-)
17
18diff --git a/lib/timeutils/tests/test_scan-timestamp.c b/lib/timeutils/tests/test_scan-timestamp.c
19index 27b76f12d..468bbf779 100644
20--- a/lib/timeutils/tests/test_scan-timestamp.c
21+++ b/lib/timeutils/tests/test_scan-timestamp.c
22@@ -50,17 +50,21 @@ fake_time_add(time_t diff)
23 }
24
25 static gboolean
26-_parse_rfc3164(const gchar *ts, gchar isotimestamp[32])
27+_parse_rfc3164(const gchar *ts, gint len, gchar isotimestamp[32])
28 {
29   UnixTime stamp;
30-  const guchar *data = (const guchar *) ts;
31-  gint length = strlen(ts);
32+  const guchar *tsu = (const guchar *) ts;
33+  gint tsu_len = len < 0 ? strlen(ts) : len;
34   GString *result = g_string_new("");
35   WallClockTime wct = WALL_CLOCK_TIME_INIT;
36
37-
38+  const guchar *data = tsu;
39+  gint length = tsu_len;
40   gboolean success = scan_rfc3164_timestamp(&data, &length, &wct);
41
42+  cr_assert(length >= 0);
43+  cr_assert(data == &tsu[tsu_len - length]);
44+
45   unix_time_unset(&stamp);
46   convert_wall_clock_time_to_unix_time(&wct, &stamp);
47
48@@ -71,16 +75,21 @@ _parse_rfc3164(const gchar *ts, gchar isotimestamp[32])
49 }
50
51 static gboolean
52-_parse_rfc5424(const gchar *ts, gchar isotimestamp[32])
53+_parse_rfc5424(const gchar *ts, gint len, gchar isotimestamp[32])
54 {
55   UnixTime stamp;
56-  const guchar *data = (const guchar *) ts;
57-  gint length = strlen(ts);
58+  const guchar *tsu = (const guchar *) ts;
59+  gint tsu_len = len < 0 ? strlen(ts) : len;
60   GString *result = g_string_new("");
61   WallClockTime wct = WALL_CLOCK_TIME_INIT;
62
63+  const guchar *data = tsu;
64+  gint length = tsu_len;
65   gboolean success = scan_rfc5424_timestamp(&data, &length, &wct);
66
67+  cr_assert(length >= 0);
68+  cr_assert(data == &tsu[tsu_len - length]);
69+
70   unix_time_unset(&stamp);
71   convert_wall_clock_time_to_unix_time(&wct, &stamp);
72
73@@ -91,31 +100,60 @@ _parse_rfc5424(const gchar *ts, gchar isotimestamp[32])
74 }
75
76 static gboolean
77-_rfc3164_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32])
78+_rfc3164_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32])
79 {
80-  cr_assert(_parse_rfc3164(ts, converted));
81+  cr_assert(_parse_rfc3164(ts, len, converted));
82   return strcmp(converted, expected) == 0;
83 }
84
85 static gboolean
86-_rfc5424_timestamp_eq(const gchar *ts, const gchar *expected, gchar converted[32])
87+_rfc5424_timestamp_eq(const gchar *ts, gint len, const gchar *expected, gchar converted[32])
88 {
89-  cr_assert(_parse_rfc5424(ts, converted));
90+  cr_assert(_parse_rfc5424(ts, len, converted));
91   return strcmp(converted, expected) == 0;
92 }
93
94 #define _expect_rfc3164_timestamp_eq(ts, expected) \
95   ({ \
96     gchar converted[32]; \
97-    cr_expect(_rfc3164_timestamp_eq(ts, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
98+    cr_expect(_rfc3164_timestamp_eq(ts, -1, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
99+  })
100+
101+#define _expect_rfc3164_timestamp_len_eq(ts, len, expected) \
102+  ({ \
103+    gchar converted[32]; \
104+    cr_expect(_rfc3164_timestamp_eq(ts, len, expected, converted), "Parsed RFC3164 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
105+  })
106+
107+#define _expect_rfc3164_fails(ts, len) \
108+  ({  \
109+    WallClockTime wct = WALL_CLOCK_TIME_INIT; \
110+    const guchar *data = (guchar *) ts; \
111+    gint length = len < 0 ? strlen(ts) : len; \
112+    cr_assert_not(scan_rfc3164_timestamp(&data, &length, &wct)); \
113   })
114
115 #define _expect_rfc5424_timestamp_eq(ts, expected) \
116   ({ \
117     gchar converted[32]; \
118-    cr_expect(_rfc5424_timestamp_eq(ts, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
119+    cr_expect(_rfc5424_timestamp_eq(ts, -1, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
120+  })
121+
122+#define _expect_rfc5424_timestamp_len_eq(ts, len, expected) \
123+  ({ \
124+    gchar converted[32]; \
125+    cr_expect(_rfc5424_timestamp_eq(ts, len, expected, converted), "Parsed RFC5424 timestamp does not equal expected, ts=%s, converted=%s, expected=%s", ts, converted, expected); \
126+  })
127+
128+#define _expect_rfc5424_fails(ts, len) \
129+  ({  \
130+    WallClockTime wct = WALL_CLOCK_TIME_INIT; \
131+    const guchar *data = (guchar *) ts; \
132+    gint length = len < 0 ? strlen(ts) : len; \
133+    cr_assert_not(scan_rfc5424_timestamp(&data, &length, &wct)); \
134   })
135
136+
137 Test(parse_timestamp, standard_bsd_format)
138 {
139   _expect_rfc3164_timestamp_eq("Oct  1 17:46:12", "2017-10-01T17:46:12.000+02:00");
140@@ -164,6 +202,68 @@ Test(parse_timestamp, standard_bsd_format_year_in_the_past)
141   _expect_rfc3164_timestamp_eq("Dec 31 17:46:12", "2017-12-31T17:46:12.000+01:00");
142 }
143
144+Test(parse_timestamp, non_zero_terminated_rfc3164_iso_input_is_handled_properly)
145+{
146+  gchar *ts = "2022-08-17T05:02:28.417Z whatever";
147+  gint ts_len = 24;
148+
149+  _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00");
150+  _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00");
151+  _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00");
152+
153+  /* no "Z" parsed, timezone defaults to local, forced CET */
154+  _expect_rfc3164_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00");
155+
156+  /* msec is partially parsed as we trim the string from the right */
157+  _expect_rfc3164_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00");
158+  _expect_rfc3164_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00");
159+  _expect_rfc3164_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00");
160+  _expect_rfc3164_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00");
161+
162+  for (gint i = 6; i < ts_len; i++)
163+    _expect_rfc3164_fails(ts, ts_len - i);
164+
165+}
166+
167+Test(parse_timestamp, non_zero_terminated_rfc3164_bsd_pix_or_asa_input_is_handled_properly)
168+{
169+  gchar *ts = "Aug 17 2022 05:02:28: whatever";
170+  gint ts_len = 21;
171+
172+  _expect_rfc3164_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.000+02:00");
173+  _expect_rfc3164_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.000+02:00");
174+  _expect_rfc3164_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.000+02:00");
175+
176+  /* no ":" at the end, that's a problem, unrecognized */
177+  _expect_rfc3164_fails(ts, ts_len - 1);
178+
179+  for (gint i = 1; i < ts_len; i++)
180+    _expect_rfc3164_fails(ts, ts_len - i);
181+}
182+
183+Test(parse_timestamp, non_zero_terminated_rfc5424_input_is_handled_properly)
184+{
185+  gchar *ts = "2022-08-17T05:02:28.417Z whatever";
186+  gint ts_len = 24;
187+
188+  _expect_rfc5424_timestamp_len_eq(ts, strlen(ts), "2022-08-17T05:02:28.417+00:00");
189+  _expect_rfc5424_timestamp_len_eq(ts, ts_len + 5, "2022-08-17T05:02:28.417+00:00");
190+  _expect_rfc5424_timestamp_len_eq(ts, ts_len, "2022-08-17T05:02:28.417+00:00");
191+
192+  /* no "Z" parsed, timezone defaults to local, forced CET */
193+  _expect_rfc5424_timestamp_len_eq(ts, ts_len - 1, "2022-08-17T05:02:28.417+02:00");
194+
195+  /* msec is partially parsed as we trim the string from the right */
196+  _expect_rfc5424_timestamp_len_eq(ts, ts_len - 2, "2022-08-17T05:02:28.410+02:00");
197+  _expect_rfc5424_timestamp_len_eq(ts, ts_len - 3, "2022-08-17T05:02:28.400+02:00");
198+  _expect_rfc5424_timestamp_len_eq(ts, ts_len - 4, "2022-08-17T05:02:28.000+02:00");
199+  _expect_rfc5424_timestamp_len_eq(ts, ts_len - 5, "2022-08-17T05:02:28.000+02:00");
200+
201+  for (gint i = 6; i < ts_len; i++)
202+    _expect_rfc5424_fails(ts, ts_len - i);
203+
204+}
205+
206
207 Test(parse_timestamp, daylight_saving_behavior_at_spring_with_explicit_timezones)
208 {
209--
2102.34.1
211
212