diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-10-27 06:37:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-27 06:37:52 +0800 |
commit | 9dc440400cdb470b317c4169ba916e1cd9a316e1 (patch) | |
tree | 2f262ee163ae432bb692cb941c69eddf17c2d836 | |
parent | ba6761eafe615a7f904c585dba3b7d6e98f665e1 (diff) | |
download | rneovim-9dc440400cdb470b317c4169ba916e1cd9a316e1.tar.gz rneovim-9dc440400cdb470b317c4169ba916e1cd9a316e1.tar.bz2 rneovim-9dc440400cdb470b317c4169ba916e1cd9a316e1.zip |
vim-patch:9.0.2068: [security] overflow in :history (#25794)
Problem: [security] overflow in :history
Solution: Check that value fits into int
The get_list_range() function, used to parse numbers for the :history
and :clist command internally uses long variables to store the numbers.
However function arguments are integer pointers, which can then
overflow.
Check that the return value from the vim_str2nr() function is not larger
than INT_MAX and if yes, bail out with an error. I guess nobody uses a
cmdline/clist history that needs so many entries... (famous last words).
It is only a moderate vulnerability, so impact should be low.
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-q22m-h7m2-9mgm
https://github.com/vim/vim/commit/9198c1f2b1ddecde22af918541e0de2a32f0f45a
N/A patch:
vim-patch:9.0.2073: typo in quickfix.c comments
Co-authored-by: Christian Brabandt <cb@256bit.org>
-rw-r--r-- | src/nvim/cmdhist.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 12 | ||||
-rw-r--r-- | test/old/testdir/test_history.vim | 8 |
3 files changed, 26 insertions, 2 deletions
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c index b0490670fe..f1c57c4613 100644 --- a/src/nvim/cmdhist.c +++ b/src/nvim/cmdhist.c @@ -34,6 +34,8 @@ # include "cmdhist.c.generated.h" #endif +static const char e_val_too_large[] = N_("E1510: Value too large: %s"); + static histentry_T *(history[HIST_COUNT]) = { NULL, NULL, NULL, NULL, NULL }; static int hisidx[HIST_COUNT] = { -1, -1, -1, -1, -1 }; ///< lastused entry /// identifying (unique) number of newest history entry @@ -637,7 +639,11 @@ void ex_history(exarg_T *eap) end = arg; } if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) { - semsg(_(e_trailing_arg), end); + if (*end != NUL) { + semsg(_(e_trailing_arg), end); + } else { + semsg(_(e_val_too_large), arg); + } return; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 9d0e3d542a..93fd62f107 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4241,6 +4241,11 @@ int get_list_range(char **str, int *num1, int *num2) if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); *str += len; + // overflow + if (num > INT_MAX) { + return FAIL; + } + *num1 = (int)num; first = true; } @@ -4249,8 +4254,13 @@ int get_list_range(char **str, int *num1, int *num2) *str = skipwhite((*str) + 1); vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); if (len > 0) { - *num2 = (int)num; *str = skipwhite((*str) + len); + // overflow + if (num > INT_MAX) { + return FAIL; + } + + *num2 = (int)num; } else if (!first) { // no number given at all return FAIL; } diff --git a/test/old/testdir/test_history.vim b/test/old/testdir/test_history.vim index bb6d671725..482328ab4a 100644 --- a/test/old/testdir/test_history.vim +++ b/test/old/testdir/test_history.vim @@ -254,4 +254,12 @@ func Test_history_crypt_key() set key& bs& ts& endfunc +" The following used to overflow and causing an use-after-free +func Test_history_max_val() + + set history=10 + call assert_fails(':history 2147483648', 'E1510:') + set history& +endfunc + " vim: shiftwidth=2 sts=2 expandtab |