mirror of
https://github.com/neovim/neovim.git
synced 2025-10-03 16:36:30 +00:00
eval/decode: Avoid overflow when parsing incomplete null/true/false
Note: second test does not crash or produce asan errors, even though it should.
This commit is contained in:
@@ -334,7 +334,7 @@ json_decode_string_cycle_start:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 'n': {
|
case 'n': {
|
||||||
if (strncmp(p + 1, "ull", 3) != 0) {
|
if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) {
|
||||||
EMSG2(_("E474: Expected null: %s"), p);
|
EMSG2(_("E474: Expected null: %s"), p);
|
||||||
goto json_decode_string_fail;
|
goto json_decode_string_fail;
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ json_decode_string_cycle_start:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 't': {
|
case 't': {
|
||||||
if (strncmp(p + 1, "rue", 3) != 0) {
|
if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) {
|
||||||
EMSG2(_("E474: Expected true: %s"), p);
|
EMSG2(_("E474: Expected true: %s"), p);
|
||||||
goto json_decode_string_fail;
|
goto json_decode_string_fail;
|
||||||
}
|
}
|
||||||
@@ -360,7 +360,7 @@ json_decode_string_cycle_start:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f': {
|
case 'f': {
|
||||||
if (strncmp(p + 1, "alse", 4) != 0) {
|
if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) {
|
||||||
EMSG2(_("E474: Expected false: %s"), p);
|
EMSG2(_("E474: Expected false: %s"), p);
|
||||||
goto json_decode_string_fail;
|
goto json_decode_string_fail;
|
||||||
}
|
}
|
||||||
|
65
test/unit/eval/decode_spec.lua
Normal file
65
test/unit/eval/decode_spec.lua
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
local ffi = require('ffi')
|
||||||
|
local helpers = require('test.unit.helpers')
|
||||||
|
local eval_helpers = require('test.unit.eval.helpers')
|
||||||
|
|
||||||
|
local cimport = helpers.cimport
|
||||||
|
local to_cstr = helpers.to_cstr
|
||||||
|
local eq = helpers.eq
|
||||||
|
|
||||||
|
local list = eval_helpers.list
|
||||||
|
local lst2tbl = eval_helpers.lst2tbl
|
||||||
|
local type_key = eval_helpers.type_key
|
||||||
|
local list_type = eval_helpers.list_type
|
||||||
|
local null_string = eval_helpers.null_string
|
||||||
|
|
||||||
|
local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval_defs.h',
|
||||||
|
'./src/nvim/globals.h', './src/nvim/memory.h')
|
||||||
|
|
||||||
|
describe('json_decode_string()', function()
|
||||||
|
after_each(function()
|
||||||
|
decode.emsg_silent = 0
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not overflow when running with `n…`, `t…`, `f…`', function()
|
||||||
|
local rettv = ffi.new('typval_T')
|
||||||
|
decode.emsg_silent = 1
|
||||||
|
rettv.v_type = decode.VAR_UNKNOWN
|
||||||
|
-- This will not crash, but if `len` argument will be ignored it will parse
|
||||||
|
-- `null` as `null` and if not it will parse `null` as `n`.
|
||||||
|
eq(0, decode.json_decode_string('null', 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('true', 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('false', 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('null', 2, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('true', 2, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('false', 2, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('null', 3, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('true', 3, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('false', 3, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string('false', 4, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not overflow and crash when running with `n`, `t`, `f`', function()
|
||||||
|
local rettv = ffi.new('typval_T')
|
||||||
|
decode.emsg_silent = 1
|
||||||
|
rettv.v_type = decode.VAR_UNKNOWN
|
||||||
|
local char = function(c)
|
||||||
|
return ffi.gc(decode.xmemdup(c, 1), decode.xfree)
|
||||||
|
end
|
||||||
|
eq(0, decode.json_decode_string(char('n'), 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string(char('t'), 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
eq(0, decode.json_decode_string(char('f'), 1, rettv))
|
||||||
|
eq(decode.VAR_UNKNOWN, rettv.v_type)
|
||||||
|
end)
|
||||||
|
end)
|
Reference in New Issue
Block a user