1
0
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:
Max Lv
2026-06-17 11:26:32 +08:00
committed by GitHub
3 changed files with 34 additions and 6 deletions

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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;