Skip to content

Commit e8fc355

Browse files
Andy YeAndy Ye
authored andcommitted
Fix truncated UDP and JSON bounds checks
1 parent 8ad3036 commit e8fc355

3 files changed

Lines changed: 34 additions & 6 deletions

File tree

src/json.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ json_value * json_parse_ex (json_settings * settings,
304304
case 't': string_add ('\t'); break;
305305
case 'u':
306306

307-
if (end - state.ptr < 4 ||
307+
if (end - state.ptr <= 4 ||
308308
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
309309
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
310310
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
@@ -321,7 +321,7 @@ json_value * json_parse_ex (json_settings * settings,
321321
if ((uchar & 0xF800) == 0xD800) {
322322
json_uchar uchar2;
323323

324-
if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
324+
if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
325325
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
326326
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
327327
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
@@ -600,7 +600,7 @@ json_value * json_parse_ex (json_settings * settings,
600600

601601
case 't':
602602

603-
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
603+
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'r' ||
604604
*(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
605605
{
606606
goto e_unknown_value;
@@ -616,7 +616,7 @@ json_value * json_parse_ex (json_settings * settings,
616616

617617
case 'f':
618618

619-
if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
619+
if ((end - state.ptr) <= 4 || *(++ state.ptr) != 'a' ||
620620
*(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
621621
*(++ state.ptr) != 'e')
622622
{
@@ -631,7 +631,7 @@ json_value * json_parse_ex (json_settings * settings,
631631

632632
case 'n':
633633

634-
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
634+
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'u' ||
635635
*(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
636636
{
637637
goto e_unknown_value;
@@ -1032,4 +1032,3 @@ void json_value_free (json_value * value)
10321032
settings.mem_free = default_free;
10331033
json_value_free_ex (&settings, value);
10341034
}
1035-

src/udprelay.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ static int
245245
parse_udprelay_header(const char *buf, const size_t buf_len,
246246
char *host, char *port, struct sockaddr_storage *storage)
247247
{
248+
if (buf_len < 1) {
249+
return 0;
250+
}
251+
248252
const uint8_t atyp = *(uint8_t *)buf;
249253
int offset = 1;
250254

@@ -267,6 +271,9 @@ parse_udprelay_header(const char *buf, const size_t buf_len,
267271
}
268272
} else if ((atyp & ADDRTYPE_MASK) == 3) {
269273
// Domain name
274+
if (buf_len < offset + 1) {
275+
return 0;
276+
}
270277
uint8_t name_len = *(uint8_t *)(buf + offset);
271278
if (name_len + 4 <= buf_len) {
272279
if (storage != NULL) {

tests/test_json.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,26 @@ test_parse_invalid(void)
9494
assert(json_parse("not json", 8) == NULL);
9595
}
9696

97+
static void
98+
test_parse_truncated_escape_sequences(void)
99+
{
100+
/* Four bytes remain after 'u', but the fourth hex read would hit EOF. */
101+
const char *truncated_unicode_escape = "\"\\uB2D";
102+
assert(json_parse(truncated_unicode_escape, strlen(truncated_unicode_escape)) == NULL);
103+
104+
/* Six bytes remain after the high surrogate, but the sixth read would hit EOF. */
105+
const char *truncated_surrogate_pair = "\"\\udfff\\ufff";
106+
assert(json_parse(truncated_surrogate_pair, strlen(truncated_surrogate_pair)) == NULL);
107+
}
108+
109+
static void
110+
test_parse_truncated_literals(void)
111+
{
112+
assert(json_parse("tru", 3) == NULL);
113+
assert(json_parse("fals", 4) == NULL);
114+
assert(json_parse("nul", 3) == NULL);
115+
}
116+
97117
static void
98118
test_parse_empty_object(void)
99119
{
@@ -124,6 +144,8 @@ main(void)
124144
test_parse_nested();
125145
test_parse_types();
126146
test_parse_invalid();
147+
test_parse_truncated_escape_sequences();
148+
test_parse_truncated_literals();
127149
test_parse_empty_object();
128150
test_parse_empty_array();
129151
return 0;

0 commit comments

Comments
 (0)