aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZyX <kp-pav@yandex.ru>2016-03-10 01:06:43 +0300
committerZyX <kp-pav@yandex.ru>2016-04-18 02:48:20 +0300
commitd06c2a1b1846a96a45625ad5472a235b2d249933 (patch)
tree963e2c8fc0186f15127be9f55310a2120f1226ff
parent2b0d46195be0792791171aa23d04ee7ba31c54c9 (diff)
downloadrneovim-d06c2a1b1846a96a45625ad5472a235b2d249933.tar.gz
rneovim-d06c2a1b1846a96a45625ad5472a235b2d249933.tar.bz2
rneovim-d06c2a1b1846a96a45625ad5472a235b2d249933.zip
eval/decode: Do not overflow when parsing `-`
Also makes if’s less nested.
-rw-r--r--src/nvim/eval/decode.c38
-rw-r--r--test/unit/eval/decode_spec.lua20
2 files changed, 35 insertions, 23 deletions
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 1303e288c3..2e9bf8fbac 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -503,6 +503,9 @@ static inline int parse_json_number(const char *const buf, const size_t buf_len,
p++;
}
ints = p;
+ if (p >= e) {
+ goto parse_json_number_check;
+ }
while (p < e && ascii_isdigit(*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));
goto parse_json_number_fail;
}
- if (p < e && p != ints && (*p == '.' || *p == 'e' || *p == 'E')) {
- if (*p == '.') {
+ if (p >= e || p == ints) {
+ goto parse_json_number_check;
+ }
+ if (*p == '.') {
+ p++;
+ fracs = p;
+ while (p < e && ascii_isdigit(*p)) {
p++;
- fracs = p;
- while (p < e && ascii_isdigit(*p)) {
- p++;
- }
}
- if (p < e && (*p == 'e' || *p == 'E')) {
+ if (p >= e || p == fracs) {
+ goto parse_json_number_check;
+ }
+ }
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ exps_s = p;
+ if (p < e && (*p == '-' || *p == '+')) {
+ p++;
+ }
+ exps = p;
+ while (p < e && ascii_isdigit(*p)) {
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) {
emsgf(_("E474: Missing number after minus sign: %.*s"), LENP(s, e));
goto parse_json_number_fail;
diff --git a/test/unit/eval/decode_spec.lua b/test/unit/eval/decode_spec.lua
index 57fc5f7b94..44471c1877 100644
--- a/test/unit/eval/decode_spec.lua
+++ b/test/unit/eval/decode_spec.lua
@@ -76,15 +76,15 @@ describe('json_decode_string()', function()
eq(decode.VAR_UNKNOWN, rettv.v_type)
end)
- it('does not overflow in error messages', function()
- 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 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
+
+ it('does not overflow in error messages', function()
check_failure(']test', 1, 'E474: No container to close: ]')
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
check_failure('{]test', 2,
@@ -129,6 +129,10 @@ describe('json_decode_string()', function()
check_failure('[1test', 2, 'E474: Unexpected end of input: [1')
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()
local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
decode.emsg_silent = 1