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

9198c1f2b1

N/A patch:
vim-patch:9.0.2073: typo in quickfix.c comments

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq 2023-10-27 06:37:52 +08:00 committed by GitHub
parent ba6761eafe
commit 9dc440400c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 2 deletions

View File

@ -34,6 +34,8 @@
# include "cmdhist.c.generated.h" # include "cmdhist.c.generated.h"
#endif #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 histentry_T *(history[HIST_COUNT]) = { NULL, NULL, NULL, NULL, NULL };
static int hisidx[HIST_COUNT] = { -1, -1, -1, -1, -1 }; ///< lastused entry static int hisidx[HIST_COUNT] = { -1, -1, -1, -1, -1 }; ///< lastused entry
/// identifying (unique) number of newest history entry /// identifying (unique) number of newest history entry
@ -637,7 +639,11 @@ void ex_history(exarg_T *eap)
end = arg; end = arg;
} }
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) { 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; return;
} }

View File

@ -4241,6 +4241,11 @@ int get_list_range(char **str, int *num1, int *num2)
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL);
*str += len; *str += len;
// overflow
if (num > INT_MAX) {
return FAIL;
}
*num1 = (int)num; *num1 = (int)num;
first = true; first = true;
} }
@ -4249,8 +4254,13 @@ int get_list_range(char **str, int *num1, int *num2)
*str = skipwhite((*str) + 1); *str = skipwhite((*str) + 1);
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL);
if (len > 0) { if (len > 0) {
*num2 = (int)num;
*str = skipwhite((*str) + len); *str = skipwhite((*str) + len);
// overflow
if (num > INT_MAX) {
return FAIL;
}
*num2 = (int)num;
} else if (!first) { // no number given at all } else if (!first) { // no number given at all
return FAIL; return FAIL;
} }

View File

@ -254,4 +254,12 @@ func Test_history_crypt_key()
set key& bs& ts& set key& bs& ts&
endfunc 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 " vim: shiftwidth=2 sts=2 expandtab