mirror of
https://github.com/neovim/neovim.git
synced 2026-04-01 05:12:02 +00:00
fix(prompt): heap-buffer-overflow in prompt_setprompt
Problem: prompt_setprompt may check the wrong buffer, which can lead to a heap-buffer-overflow. Solution: don't use curbuf. Also replace all kCallbackNone initializers with CALLBACK_INIT.
This commit is contained in:
@@ -712,7 +712,7 @@ void restore_buffer(bufref_T *save_curbuf)
|
||||
/// "prompt_setcallback({buffer}, {callback})" function
|
||||
void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
Callback prompt_callback = { .type = kCallbackNone };
|
||||
Callback prompt_callback = CALLBACK_INIT;
|
||||
|
||||
if (check_secure()) {
|
||||
return;
|
||||
@@ -735,7 +735,7 @@ void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
/// "prompt_setinterrupt({buffer}, {callback})" function
|
||||
void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
Callback interrupt_callback = { .type = kCallbackNone };
|
||||
Callback interrupt_callback = CALLBACK_INIT;
|
||||
|
||||
if (check_secure()) {
|
||||
return;
|
||||
@@ -772,10 +772,8 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
// Update the prompt-text and prompt-marks if a plugin calls prompt_setprompt()
|
||||
// even while user is editing their input.
|
||||
if (bt_prompt(buf)) {
|
||||
if (buf->b_prompt_start.mark.lnum > buf->b_ml.ml_line_count) {
|
||||
// In case the mark is set to a nonexistent line.
|
||||
buf->b_prompt_start.mark.lnum = buf->b_ml.ml_line_count;
|
||||
}
|
||||
// In case the mark is set to a nonexistent line.
|
||||
buf->b_prompt_start.mark.lnum = MIN(buf->b_prompt_start.mark.lnum, buf->b_ml.ml_line_count);
|
||||
|
||||
linenr_T prompt_lno = buf->b_prompt_start.mark.lnum;
|
||||
char *old_prompt = buf_prompt_text(buf);
|
||||
@@ -786,8 +784,7 @@ void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
colnr_T cursor_col = curwin->w_cursor.col;
|
||||
|
||||
if (buf->b_prompt_start.mark.col < old_prompt_len
|
||||
|| curbuf->b_prompt_start.mark.col < old_prompt_len
|
||||
|| !strnequal(old_prompt, old_line + curbuf->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)) {
|
||||
// If for some odd reason the old prompt is missing,
|
||||
// replace prompt line with new-prompt (discards user-input).
|
||||
|
||||
@@ -4883,7 +4883,7 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const
|
||||
typval_T *cancelreturn = NULL;
|
||||
typval_T cancelreturn_strarg2 = TV_INITIAL_VALUE;
|
||||
const char *xp_name = NULL;
|
||||
Callback input_callback = { .type = kCallbackNone };
|
||||
Callback input_callback = CALLBACK_INIT;
|
||||
char prompt_buf[NUMBUFLEN];
|
||||
char defstr_buf[NUMBUFLEN];
|
||||
char cancelreturn_buf[NUMBUFLEN];
|
||||
|
||||
@@ -798,8 +798,8 @@ describe('prompt buffer', function()
|
||||
api.nvim_set_option_value('buftype', 'prompt', { buf = 0 })
|
||||
local buf = api.nvim_get_current_buf()
|
||||
|
||||
local function set_prompt(prompt)
|
||||
fn('prompt_setprompt', buf, prompt)
|
||||
local function set_prompt(prompt, b)
|
||||
fn('prompt_setprompt', b or buf, prompt)
|
||||
end
|
||||
|
||||
set_prompt('> ')
|
||||
@@ -846,5 +846,20 @@ describe('prompt buffer', function()
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
eq({ 1, 13 }, api.nvim_buf_get_mark(0, ':'))
|
||||
|
||||
-- No crash when setting shorter prompt than curbuf's in other buffer.
|
||||
command('new | setlocal buftype=prompt')
|
||||
set_prompt('looooooooooooooooooooooooooooooooooooooooooooong > ', '') -- curbuf
|
||||
set_prompt('foo > ')
|
||||
screen:expect([[
|
||||
loooooooooooooooooooooooo|
|
||||
ooooooooooooooooooooong >|
|
||||
^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
foo > user input |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user