mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 21:25:04 -07:00
vim-patch:9.0.2142: [security]: stack-buffer-overflow in option callback functions
Problem: [security]: stack-buffer-overflow in option callback functions
Solution: pass size of errbuf down the call stack, use snprintf()
instead of sprintf()
We pass the error buffer down to the option callback functions, but in
some parts of the code, we simply use sprintf(buf) to write into the error
buffer, which can overflow.
So let's pass down the length of the error buffer and use sprintf(buf, size)
instead.
Reported by @henices, thanks!
b39b240c38
Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
parent
01edcd6db8
commit
9cc346119b
@ -1455,7 +1455,7 @@ int do_set(char *arg, int opt_flags)
|
|||||||
} else {
|
} else {
|
||||||
char *startarg = arg; // remember for error message
|
char *startarg = arg; // remember for error message
|
||||||
const char *errmsg = NULL;
|
const char *errmsg = NULL;
|
||||||
char errbuf[80];
|
char errbuf[ERR_BUFLEN];
|
||||||
|
|
||||||
do_one_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
|
do_one_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
|
||||||
|
|
||||||
@ -3845,7 +3845,7 @@ const char *set_option_value(const char *const name, const OptVal value, int opt
|
|||||||
|
|
||||||
int opt_idx = findoption(name);
|
int opt_idx = findoption(name);
|
||||||
if (opt_idx < 0) {
|
if (opt_idx < 0) {
|
||||||
snprintf(errbuf, IOSIZE, _(e_unknown_option2), name);
|
snprintf(errbuf, sizeof(errbuf), _(e_unknown_option2), name);
|
||||||
return errbuf;
|
return errbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ typedef struct {
|
|||||||
/// is parameterized, then the "os_errbuf" buffer is used to store the error
|
/// is parameterized, then the "os_errbuf" buffer is used to store the error
|
||||||
/// message (when it is not NULL).
|
/// message (when it is not NULL).
|
||||||
char *os_errbuf;
|
char *os_errbuf;
|
||||||
|
/// length of the error buffer
|
||||||
size_t os_errbuflen;
|
size_t os_errbuflen;
|
||||||
|
|
||||||
void *os_win;
|
void *os_win;
|
||||||
|
@ -938,6 +938,8 @@ enum {
|
|||||||
// Value for b_p_ul indicating the global value must be used.
|
// Value for b_p_ul indicating the global value must be used.
|
||||||
#define NO_LOCAL_UNDOLEVEL (-123456)
|
#define NO_LOCAL_UNDOLEVEL (-123456)
|
||||||
|
|
||||||
|
#define ERR_BUFLEN 80
|
||||||
|
|
||||||
#define SB_MAX 100000 // Maximum 'scrollback' value.
|
#define SB_MAX 100000 // Maximum 'scrollback' value.
|
||||||
|
|
||||||
#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
|
#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
|
||||||
|
@ -442,7 +442,7 @@ int check_signcolumn(win_T *wp)
|
|||||||
const char *check_stl_option(char *s)
|
const char *check_stl_option(char *s)
|
||||||
{
|
{
|
||||||
int groupdepth = 0;
|
int groupdepth = 0;
|
||||||
static char errbuf[80];
|
static char errbuf[ERR_BUFLEN];
|
||||||
|
|
||||||
while (*s) {
|
while (*s) {
|
||||||
// Check for valid keys after % sequences
|
// Check for valid keys after % sequences
|
||||||
|
@ -21,3 +21,13 @@ it('no crash when ending Visual mode close the window to switch to', function()
|
|||||||
command('wincmd p')
|
command('wincmd p')
|
||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('no crash when truncating overlong message', function()
|
||||||
|
pcall(command, 'source test/old/testdir/crash/vim_msg_trunc_poc')
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('no crash with very long option error message', function()
|
||||||
|
pcall(command, 'source test/old/testdir/crash/poc_did_set_langmap')
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
|
@ -801,9 +801,4 @@ describe('messages', function()
|
|||||||
]])
|
]])
|
||||||
os.remove('b.txt')
|
os.remove('b.txt')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('no crash when truncating overlong message', function()
|
|
||||||
pcall(command, 'source test/old/testdir/crash/vim_msg_trunc_poc')
|
|
||||||
assert_alive()
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
1
test/old/testdir/crash/poc_did_set_langmap
Normal file
1
test/old/testdir/crash/poc_did_set_langmap
Normal file
@ -0,0 +1 @@
|
|||||||
|
se lmap=°xÿ7sil;drlmap=°xÿ7sil;drmo: pm313"
|
@ -142,6 +142,13 @@ func Test_crash1_2()
|
|||||||
\ ' && echo "crash 3: [OK]" >> '.. result .. "\<cr>")
|
\ ' && echo "crash 3: [OK]" >> '.. result .. "\<cr>")
|
||||||
call TermWait(buf, 150)
|
call TermWait(buf, 150)
|
||||||
|
|
||||||
|
let file = 'crash/poc_did_set_langmap'
|
||||||
|
let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
|
||||||
|
let args = printf(cmn_args, vim, file)
|
||||||
|
call term_sendkeys(buf, args ..
|
||||||
|
\ ' ; echo "crash 4: [OK]" >> '.. result .. "\<cr>")
|
||||||
|
call TermWait(buf, 150)
|
||||||
|
|
||||||
" clean up
|
" clean up
|
||||||
exe buf .. "bw!"
|
exe buf .. "bw!"
|
||||||
|
|
||||||
@ -151,6 +158,7 @@ func Test_crash1_2()
|
|||||||
\ 'crash 1: [OK]',
|
\ 'crash 1: [OK]',
|
||||||
\ 'crash 2: [OK]',
|
\ 'crash 2: [OK]',
|
||||||
\ 'crash 3: [OK]',
|
\ 'crash 3: [OK]',
|
||||||
|
\ 'crash 4: [OK]',
|
||||||
\ ]
|
\ ]
|
||||||
|
|
||||||
call assert_equal(expected, getline(1, '$'))
|
call assert_equal(expected, getline(1, '$'))
|
||||||
|
Loading…
Reference in New Issue
Block a user