mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-09-24 00:45:06 +00:00
Merge pull request #3039 from TurboTheTurtle/fix-udp-json-bounds-checks
Fix truncated UDP and JSON bounds checks
This commit is contained in:
11
src/json.c
11
src/json.c
@@ -304,7 +304,7 @@ json_value * json_parse_ex (json_settings * settings,
|
||||
case 't': string_add ('\t'); break;
|
||||
case 'u':
|
||||
|
||||
if (end - state.ptr < 4 ||
|
||||
if (end - state.ptr <= 4 ||
|
||||
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
@@ -321,7 +321,7 @@ json_value * json_parse_ex (json_settings * settings,
|
||||
if ((uchar & 0xF800) == 0xD800) {
|
||||
json_uchar uchar2;
|
||||
|
||||
if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
|
||||
if (end - state.ptr <= 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
|
||||
(uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
|
||||
@@ -600,7 +600,7 @@ json_value * json_parse_ex (json_settings * settings,
|
||||
|
||||
case 't':
|
||||
|
||||
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
|
||||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'r' ||
|
||||
*(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
|
||||
{
|
||||
goto e_unknown_value;
|
||||
@@ -616,7 +616,7 @@ json_value * json_parse_ex (json_settings * settings,
|
||||
|
||||
case 'f':
|
||||
|
||||
if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
|
||||
if ((end - state.ptr) <= 4 || *(++ state.ptr) != 'a' ||
|
||||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
|
||||
*(++ state.ptr) != 'e')
|
||||
{
|
||||
@@ -631,7 +631,7 @@ json_value * json_parse_ex (json_settings * settings,
|
||||
|
||||
case 'n':
|
||||
|
||||
if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
|
||||
if ((end - state.ptr) <= 3 || *(++ state.ptr) != 'u' ||
|
||||
*(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
|
||||
{
|
||||
goto e_unknown_value;
|
||||
@@ -1032,4 +1032,3 @@ void json_value_free (json_value * value)
|
||||
settings.mem_free = default_free;
|
||||
json_value_free_ex (&settings, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -245,6 +245,10 @@ static int
|
||||
parse_udprelay_header(const char *buf, const size_t buf_len,
|
||||
char *host, char *port, struct sockaddr_storage *storage)
|
||||
{
|
||||
if (buf_len < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t atyp = *(uint8_t *)buf;
|
||||
int offset = 1;
|
||||
|
||||
@@ -267,6 +271,9 @@ parse_udprelay_header(const char *buf, const size_t buf_len,
|
||||
}
|
||||
} else if ((atyp & ADDRTYPE_MASK) == 3) {
|
||||
// Domain name
|
||||
if (buf_len < offset + 1) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t name_len = *(uint8_t *)(buf + offset);
|
||||
if (name_len + 4 <= buf_len) {
|
||||
if (storage != NULL) {
|
||||
|
||||
@@ -94,6 +94,26 @@ test_parse_invalid(void)
|
||||
assert(json_parse("not json", 8) == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_truncated_escape_sequences(void)
|
||||
{
|
||||
/* Four bytes remain after 'u', but the fourth hex read would hit EOF. */
|
||||
const char *truncated_unicode_escape = "\"\\uB2D";
|
||||
assert(json_parse(truncated_unicode_escape, strlen(truncated_unicode_escape)) == NULL);
|
||||
|
||||
/* Six bytes remain after the high surrogate, but the sixth read would hit EOF. */
|
||||
const char *truncated_surrogate_pair = "\"\\udfff\\ufff";
|
||||
assert(json_parse(truncated_surrogate_pair, strlen(truncated_surrogate_pair)) == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_truncated_literals(void)
|
||||
{
|
||||
assert(json_parse("tru", 3) == NULL);
|
||||
assert(json_parse("fals", 4) == NULL);
|
||||
assert(json_parse("nul", 3) == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_parse_empty_object(void)
|
||||
{
|
||||
@@ -124,6 +144,8 @@ main(void)
|
||||
test_parse_nested();
|
||||
test_parse_types();
|
||||
test_parse_invalid();
|
||||
test_parse_truncated_escape_sequences();
|
||||
test_parse_truncated_literals();
|
||||
test_parse_empty_object();
|
||||
test_parse_empty_array();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user