aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-10-27 06:37:52 +0800
committerGitHub <noreply@github.com>2023-10-27 06:37:52 +0800
commit9dc440400cdb470b317c4169ba916e1cd9a316e1 (patch)
tree2f262ee163ae432bb692cb941c69eddf17c2d836
parentba6761eafe615a7f904c585dba3b7d6e98f665e1 (diff)
downloadrneovim-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.c8
-rw-r--r--src/nvim/ex_getln.c12
-rw-r--r--test/old/testdir/test_history.vim8
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