mirror of
https://github.com/neovim/neovim.git
synced 2025-12-15 19:05:40 +00:00
fix(rpc): "grid_line" event parsing crashes (#25581)
refactor: use a more idiomatic loop to iterate over the cells There are two cases in which the following assertion would fail: ```c assert(g->icell < g->ncells); ``` 1. If `g->ncells = 0`. Update this to be legal. 2. If an EOF is reached while parsing `wrap`. In this case, the unpacker attempts to resume from `cells`, which is a bug. Create a new state for parsing `wrap`. Reference: https://neovim.io/doc/user/ui.html#ui-event-grid_line
This commit is contained in:
75
test/unit/msgpack_spec.lua
Normal file
75
test/unit/msgpack_spec.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
local helpers = require('test.unit.helpers')(after_each)
|
||||
local cimport = helpers.cimport
|
||||
local itp = helpers.gen_itp(it)
|
||||
local lib = cimport('./src/nvim/msgpack_rpc/unpacker.h', './src/nvim/memory.h')
|
||||
local ffi = helpers.ffi
|
||||
local eq = helpers.eq
|
||||
local to_cstr = helpers.to_cstr
|
||||
|
||||
--- @class Unpacker
|
||||
--- @field read_ptr ffi.cdata*
|
||||
--- @field read_size number
|
||||
|
||||
--- @alias Unpacker* table<number, Unpacker>
|
||||
--- @return Unpacker* unpacker `unpacker[0]` to dereference
|
||||
local function make_unpacker()
|
||||
return ffi.gc(ffi.cast('Unpacker*', lib.xcalloc(1, ffi.sizeof('Unpacker'))), function(unpacker)
|
||||
lib.unpacker_teardown(unpacker, nil, nil)
|
||||
lib.xfree(unpacker)
|
||||
end)
|
||||
end
|
||||
|
||||
--- @param unpacker Unpacker*
|
||||
--- @param data string
|
||||
--- @param size number? *default: data:len()*
|
||||
local function unpacker_goto(unpacker, data, size)
|
||||
unpacker[0].read_ptr = to_cstr(data)
|
||||
unpacker[0].read_size = size or data:len()
|
||||
end
|
||||
|
||||
--- @param unpacker Unpacker*
|
||||
--- @return boolean
|
||||
local function unpacker_advance(unpacker)
|
||||
return lib.unpacker_advance(unpacker)
|
||||
end
|
||||
|
||||
describe('msgpack', function()
|
||||
describe('unpacker', function()
|
||||
itp('does not crash when paused between `cells` and `wrap` params of `grid_line` #25184', function()
|
||||
-- [kMessageTypeNotification, "redraw", [
|
||||
-- ["grid_line",
|
||||
-- [2, 0, 0, [[" " , 0, 77]], false]
|
||||
-- ]
|
||||
-- ]]
|
||||
local payload =
|
||||
'\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x91\x93\xa1\x20\x00\x4d\xc2'
|
||||
|
||||
local unpacker = make_unpacker()
|
||||
lib.unpacker_init(unpacker)
|
||||
|
||||
unpacker_goto(unpacker, payload, payload:len() - 1)
|
||||
local finished = unpacker_advance(unpacker)
|
||||
eq(finished, false)
|
||||
|
||||
unpacker[0].read_size = unpacker[0].read_size + 1
|
||||
finished = unpacker_advance(unpacker)
|
||||
eq(finished, true)
|
||||
end)
|
||||
|
||||
itp('does not crash when parsing grid_line event with 0 `cells` #25184', function()
|
||||
local unpacker = make_unpacker()
|
||||
lib.unpacker_init(unpacker)
|
||||
|
||||
unpacker_goto(unpacker,
|
||||
-- [kMessageTypeNotification, "redraw", [
|
||||
-- ["grid_line",
|
||||
-- [2, 0, 0, [], false]
|
||||
-- ]
|
||||
-- ]]
|
||||
'\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x90\xc2'
|
||||
)
|
||||
local finished = unpacker_advance(unpacker)
|
||||
eq(finished, true)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user