mirror of
https://github.com/neovim/neovim.git
synced 2026-07-19 23:51:38 +00:00
fix(prompt): heap-buffer-overflows with invalid ': col
Problem: heap-buffer-overflow in init_prompt and prompt_setprompt if ': mark has an invalid column number. Solution: consider an out-of-bounds column number as a missing prompt. Remove the check for NULL for old_line, as ml_get_buf can't return NULL.
This commit is contained in:
@@ -1593,12 +1593,13 @@ static void init_prompt(int cmdchar_todo)
|
|||||||
char *prompt = prompt_text();
|
char *prompt = prompt_text();
|
||||||
int prompt_len = (int)strlen(prompt);
|
int prompt_len = (int)strlen(prompt);
|
||||||
|
|
||||||
if (curwin->w_cursor.lnum < curbuf->b_prompt_start.mark.lnum) {
|
curwin->w_cursor.lnum = MAX(curwin->w_cursor.lnum, curbuf->b_prompt_start.mark.lnum);
|
||||||
curwin->w_cursor.lnum = curbuf->b_prompt_start.mark.lnum;
|
|
||||||
}
|
|
||||||
char *text = ml_get(curbuf->b_prompt_start.mark.lnum);
|
char *text = ml_get(curbuf->b_prompt_start.mark.lnum);
|
||||||
|
colnr_T text_len = ml_get_len(curbuf->b_prompt_start.mark.lnum);
|
||||||
|
|
||||||
if ((curbuf->b_prompt_start.mark.lnum == curwin->w_cursor.lnum
|
if ((curbuf->b_prompt_start.mark.lnum == curwin->w_cursor.lnum
|
||||||
&& (curbuf->b_prompt_start.mark.col < prompt_len
|
&& (curbuf->b_prompt_start.mark.col < prompt_len
|
||||||
|
|| curbuf->b_prompt_start.mark.col > text_len
|
||||||
|| !strnequal(text + curbuf->b_prompt_start.mark.col - prompt_len, prompt,
|
|| !strnequal(text + curbuf->b_prompt_start.mark.col - prompt_len, prompt,
|
||||||
(size_t)prompt_len)))) {
|
(size_t)prompt_len)))) {
|
||||||
// prompt is missing, insert it or append a line with it
|
// prompt is missing, insert it or append a line with it
|
||||||
|
|||||||
@@ -778,12 +778,13 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
linenr_T prompt_lno = buf->b_prompt_start.mark.lnum;
|
linenr_T prompt_lno = buf->b_prompt_start.mark.lnum;
|
||||||
char *old_prompt = buf_prompt_text(buf);
|
char *old_prompt = buf_prompt_text(buf);
|
||||||
char *old_line = ml_get_buf(buf, prompt_lno);
|
char *old_line = ml_get_buf(buf, prompt_lno);
|
||||||
old_line = old_line != NULL ? old_line : "";
|
colnr_T old_line_len = ml_get_buf_len(buf, prompt_lno);
|
||||||
|
|
||||||
int old_prompt_len = (int)strlen(old_prompt);
|
int old_prompt_len = (int)strlen(old_prompt);
|
||||||
colnr_T cursor_col = curwin->w_cursor.col;
|
colnr_T cursor_col = curwin->w_cursor.col;
|
||||||
|
|
||||||
if (buf->b_prompt_start.mark.col < old_prompt_len
|
if (buf->b_prompt_start.mark.col < old_prompt_len
|
||||||
|
|| buf->b_prompt_start.mark.col > old_line_len
|
||||||
|| !strnequal(old_prompt, old_line + buf->b_prompt_start.mark.col - old_prompt_len,
|
|| !strnequal(old_prompt, old_line + buf->b_prompt_start.mark.col - old_prompt_len,
|
||||||
(size_t)old_prompt_len)) {
|
(size_t)old_prompt_len)) {
|
||||||
// If for some odd reason the old prompt is missing,
|
// If for some odd reason the old prompt is missing,
|
||||||
|
|||||||
@@ -667,6 +667,10 @@ describe('prompt buffer', function()
|
|||||||
eq({ last_line, 6 }, api.nvim_buf_get_mark(0, ':'))
|
eq({ last_line, 6 }, api.nvim_buf_get_mark(0, ':'))
|
||||||
eq(true, api.nvim_buf_set_mark(0, ':', 1, 5, {}))
|
eq(true, api.nvim_buf_set_mark(0, ':', 1, 5, {}))
|
||||||
eq({ 1, 5 }, api.nvim_buf_get_mark(0, ':'))
|
eq({ 1, 5 }, api.nvim_buf_get_mark(0, ':'))
|
||||||
|
|
||||||
|
-- No crash from invalid col.
|
||||||
|
eq(true, api.nvim_buf_set_mark(0, ':', fn('line', '.'), 999, {}))
|
||||||
|
eq({ 12, 6 }, api.nvim_buf_get_mark(0, ':'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('prompt_getinput', function()
|
describe('prompt_getinput', function()
|
||||||
@@ -861,5 +865,17 @@ describe('prompt buffer', function()
|
|||||||
{1:~ }|*3
|
{1:~ }|*3
|
||||||
{5:-- INSERT --} |
|
{5:-- INSERT --} |
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
-- No prompt_setprompt crash from invalid ': col. Must happen in the same event.
|
||||||
|
exec_lua(function()
|
||||||
|
vim.cmd 'bwipeout!'
|
||||||
|
vim.api.nvim_buf_set_mark(0, ':', vim.fn.line('.'), 999, {})
|
||||||
|
vim.fn.prompt_setprompt('', 'new-prompt > ')
|
||||||
|
end)
|
||||||
|
screen:expect([[
|
||||||
|
new-prompt > ^ |
|
||||||
|
{1:~ }|*8
|
||||||
|
{5:-- INSERT --} |
|
||||||
|
]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|||||||
Reference in New Issue
Block a user