From 5e81687d9a4fb5d6fe734756b086aae47d64f5a4 Mon Sep 17 00:00:00 2001 From: f380cedric Date: Thu, 6 Jan 2022 10:54:33 +0100 Subject: [PATCH 1/2] vim-patch:8.2.3402: invalid memory access when using :retab with large value Problem: Invalid memory access when using :retab with large value. Solution: Check the number is positive. https://github.com/vim/vim/commit/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9 --- src/nvim/option.c | 25 ++++++++++++++++--------- src/nvim/testdir/test_retab.vim | 3 +++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index 659965b64c..9471974d2b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1993,9 +1993,9 @@ static void didset_options2(void) // Parse default for 'wildmode'. check_opt_wim(); xfree(curbuf->b_p_vsts_array); - tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array); + (void)tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array); xfree(curbuf->b_p_vts_array); - tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array); + (void)tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array); } /// Check for string options that are NULL (normally only termcap options). @@ -6368,7 +6368,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_sts_nopaste = p_sts_nopaste; buf->b_p_vsts = vim_strsave(p_vsts); if (p_vsts && p_vsts != empty_option) { - tabstop_set(p_vsts, &buf->b_p_vsts_array); + (void)tabstop_set(p_vsts, &buf->b_p_vsts_array); } else { buf->b_p_vsts_array = 0; } @@ -6448,7 +6448,7 @@ void buf_copy_options(buf_T *buf, int flags) if (dont_do_help) { buf->b_p_isk = save_p_isk; if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) { - tabstop_set(p_vts, &buf->b_p_vts_array); + (void)tabstop_set(p_vts, &buf->b_p_vts_array); } else { buf->b_p_vts_array = NULL; } @@ -6458,7 +6458,7 @@ void buf_copy_options(buf_T *buf, int flags) buf->b_p_ts = p_ts; buf->b_p_vts = vim_strsave(p_vts); if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) { - tabstop_set(p_vts, &buf->b_p_vts_array); + (void)tabstop_set(p_vts, &buf->b_p_vts_array); } else { buf->b_p_vts_array = NULL; } @@ -7151,7 +7151,7 @@ static void paste_option_changed(void) xfree(buf->b_p_vsts_array); } if (buf->b_p_vsts && buf->b_p_vsts != empty_option) { - tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array); + (void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array); } else { buf->b_p_vsts_array = 0; } @@ -7469,6 +7469,7 @@ int check_ff_value(char_u *p) // Set the integer values corresponding to the string setting of 'vartabstop'. // "array" will be set, caller must free it if needed. +// Return false for an error. bool tabstop_set(char_u *var, long **array) { long valcount = 1; @@ -7488,7 +7489,7 @@ bool tabstop_set(char_u *var, long **array) if (cp != end) { emsg(_(e_positive)); } else { - emsg(_(e_invarg)); + semsg(_(e_invarg2), cp); } return false; } @@ -7501,7 +7502,7 @@ bool tabstop_set(char_u *var, long **array) valcount++; continue; } - emsg(_(e_invarg)); + semsg(_(e_invarg2), var); return false; } @@ -7510,7 +7511,13 @@ bool tabstop_set(char_u *var, long **array) t = 1; for (cp = var; *cp != NUL;) { - (*array)[t++] = atoi((char *)cp); + int n = atoi((char *)cp); + + if (n < 0 || n > 9999) { + semsg(_(e_invarg2), cp); + return false; + } + (*array)[t++] = n; while (*cp != NUL && *cp != ',') { cp++; } diff --git a/src/nvim/testdir/test_retab.vim b/src/nvim/testdir/test_retab.vim index f11a32bade..e7b8946ccf 100644 --- a/src/nvim/testdir/test_retab.vim +++ b/src/nvim/testdir/test_retab.vim @@ -74,4 +74,7 @@ endfunc func Test_retab_error() call assert_fails('retab -1', 'E487:') call assert_fails('retab! -1', 'E487:') + call assert_fails('ret -1000', 'E487:') + call assert_fails('ret 10000', 'E475:') + call assert_fails('ret 80000000000000000000', 'E475:') endfunc From 503e6f7832dd07b077b3ae654fd7ae46e905aaf3 Mon Sep 17 00:00:00 2001 From: f380cedric Date: Tue, 18 Jan 2022 10:00:30 +0100 Subject: [PATCH 2/2] vim-patch:8.2.3403: memory leak for :retab with invalid argument Problem: Memory leak for :retab with invalid argument. Solution: Free the memory. Make error messages consistent. https://github.com/vim/vim/commit/2ddb89f8a94425cda1e5491efc80c1ccccb6e08e Changes in ex_retab are N/A (behind a non-FEAT_) and have been dropped. --- src/nvim/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/option.c b/src/nvim/option.c index 9471974d2b..bd76dbda95 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -7513,8 +7513,10 @@ bool tabstop_set(char_u *var, long **array) for (cp = var; *cp != NUL;) { int n = atoi((char *)cp); + // Catch negative values, overflow and ridiculous big values. if (n < 0 || n > 9999) { semsg(_(e_invarg2), cp); + XFREE_CLEAR(*array); return false; } (*array)[t++] = n;