eval/decode: Do not overflow when parsing -

Also makes if’s less nested.
This commit is contained in:
ZyX
2016-03-10 01:06:43 +03:00
parent 2b0d46195b
commit d06c2a1b18
2 changed files with 36 additions and 24 deletions

View File

@@ -503,6 +503,9 @@ static inline int parse_json_number(const char *const buf, const size_t buf_len,
p++; p++;
} }
ints = p; ints = p;
if (p >= e) {
goto parse_json_number_check;
}
while (p < e && ascii_isdigit(*p)) { while (p < e && ascii_isdigit(*p)) {
p++; p++;
} }
@@ -510,26 +513,31 @@ static inline int parse_json_number(const char *const buf, const size_t buf_len,
emsgf(_("E474: Leading zeroes are not allowed: %.*s"), LENP(s, e)); emsgf(_("E474: Leading zeroes are not allowed: %.*s"), LENP(s, e));
goto parse_json_number_fail; goto parse_json_number_fail;
} }
if (p < e && p != ints && (*p == '.' || *p == 'e' || *p == 'E')) { if (p >= e || p == ints) {
if (*p == '.') { goto parse_json_number_check;
}
if (*p == '.') {
p++;
fracs = p;
while (p < e && ascii_isdigit(*p)) {
p++; p++;
fracs = p;
while (p < e && ascii_isdigit(*p)) {
p++;
}
} }
if (p < e && (*p == 'e' || *p == 'E')) { if (p >= e || p == fracs) {
p++; goto parse_json_number_check;
exps_s = p;
if (p < e && (*p == '-' || *p == '+')) {
p++;
}
exps = p;
while (p < e && ascii_isdigit(*p)) {
p++;
}
} }
} }
if (*p == 'e' || *p == 'E') {
p++;
exps_s = p;
if (p < e && (*p == '-' || *p == '+')) {
p++;
}
exps = p;
while (p < e && ascii_isdigit(*p)) {
p++;
}
}
parse_json_number_check:
if (p == ints) { if (p == ints) {
emsgf(_("E474: Missing number after minus sign: %.*s"), LENP(s, e)); emsgf(_("E474: Missing number after minus sign: %.*s"), LENP(s, e));
goto parse_json_number_fail; goto parse_json_number_fail;

View File

@@ -76,15 +76,15 @@ describe('json_decode_string()', function()
eq(decode.VAR_UNKNOWN, rettv.v_type) eq(decode.VAR_UNKNOWN, rettv.v_type)
end) end)
it('does not overflow in error messages', function() local check_failure = function(s, len, msg)
local check_failure = function(s, len, msg)
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
eq(0, decode.json_decode_string(s, len, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
neq(nil, decode.last_msg_hist)
eq(msg, ffi.string(decode.last_msg_hist.msg))
end
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
eq(0, decode.json_decode_string(s, len, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
neq(nil, decode.last_msg_hist)
eq(msg, ffi.string(decode.last_msg_hist.msg))
end
it('does not overflow in error messages', function()
check_failure(']test', 1, 'E474: No container to close: ]') check_failure(']test', 1, 'E474: No container to close: ]')
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }') check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
check_failure('{]test', 2, check_failure('{]test', 2,
@@ -129,6 +129,10 @@ describe('json_decode_string()', function()
check_failure('[1test', 2, 'E474: Unexpected end of input: [1') check_failure('[1test', 2, 'E474: Unexpected end of input: [1')
end) end)
it('does not overflow with `-`', function()
check_failure('-0', 1, 'E474: Missing number after minus sign: -')
end)
it('does not overflow and crash when running with `"`', function() it('does not overflow and crash when running with `"`', function()
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN}) local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
decode.emsg_silent = 1 decode.emsg_silent = 1