# HG changeset patch # User Bram Moolenaar # Date 1643403605 -3600 # Node ID c1702fd7e716b97d856b2e83cbde4eb749cffcbf # Parent 5d1b4d8eea05b2509cda9ca292736e7f6256e731 patch 8.2.4245: ":retab 0" may cause illegal memory access Commit: https://github.com/vim/vim/commit/652dee448618589de5528a9e9a36995803f5557a Author: Bram Moolenaar Date: Fri Jan 28 20:47:49 2022 +0000 patch 8.2.4245: ":retab 0" may cause illegal memory access Problem: ":retab 0" may cause illegal memory access. Solution: Limit the value of 'tabstop' to 10000. diff --git a/src/indent.c b/src/indent.c --- a/src/indent.c +++ b/src/indent.c @@ -71,7 +71,7 @@ tabstop_set(char_u *var, int **array) int n = atoi((char *)cp); // Catch negative values, overflow and ridiculous big values. - if (n < 0 || n > 9999) + if (n < 0 || n > TABSTOP_MAX) { semsg(_(e_invalid_argument_str), cp); vim_free(*array); @@ -1649,7 +1649,7 @@ ex_retab(exarg_T *eap) emsg(_(e_argument_must_be_positive)); return; } - if (new_ts < 0 || new_ts > 9999) + if (new_ts < 0 || new_ts > TABSTOP_MAX) { semsg(_(e_invalid_argument_str), eap->arg); return; diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -3752,6 +3752,11 @@ set_num_option( errmsg = e_argument_must_be_positive; curbuf->b_p_ts = 8; } + else if (curbuf->b_p_ts > TABSTOP_MAX) + { + errmsg = e_invalid_argument; + curbuf->b_p_ts = 8; + } if (p_tm < 0) { errmsg = e_argument_must_be_positive; @@ -5983,7 +5988,7 @@ buf_copy_options(buf_T *buf, int flags) if (p_vsts && p_vsts != empty_option) (void)tabstop_set(p_vsts, &buf->b_p_vsts_array); else - buf->b_p_vsts_array = 0; + buf->b_p_vsts_array = NULL; buf->b_p_vsts_nopaste = p_vsts_nopaste ? vim_strsave(p_vsts_nopaste) : NULL; #endif @@ -6803,9 +6808,7 @@ paste_option_changed(void) if (buf->b_p_vsts) free_string_option(buf->b_p_vsts); buf->b_p_vsts = empty_option; - if (buf->b_p_vsts_array) - vim_free(buf->b_p_vsts_array); - buf->b_p_vsts_array = 0; + VIM_CLEAR(buf->b_p_vsts_array); #endif } @@ -6851,12 +6854,11 @@ paste_option_changed(void) free_string_option(buf->b_p_vsts); buf->b_p_vsts = buf->b_p_vsts_nopaste ? vim_strsave(buf->b_p_vsts_nopaste) : empty_option; - if (buf->b_p_vsts_array) - vim_free(buf->b_p_vsts_array); + vim_free(buf->b_p_vsts_array); if (buf->b_p_vsts && buf->b_p_vsts != empty_option) (void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array); else - buf->b_p_vsts_array = 0; + buf->b_p_vsts_array = NULL; #endif } diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -368,6 +368,8 @@ func Test_set_errors() call assert_fails('set shiftwidth=-1', 'E487:') call assert_fails('set sidescroll=-1', 'E487:') call assert_fails('set tabstop=-1', 'E487:') + call assert_fails('set tabstop=10000', 'E474:') + call assert_fails('set tabstop=5500000000', 'E474:') call assert_fails('set textwidth=-1', 'E487:') call assert_fails('set timeoutlen=-1', 'E487:') call assert_fails('set updatecount=-1', 'E487:') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4245, +/**/ 4244, /**/ 4243, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -2085,6 +2085,8 @@ typedef int sock_T; #define DICT_MAXNEST 100 // maximum nesting of lists and dicts +#define TABSTOP_MAX 9999 + #ifdef FEAT_CLIPBOARD // VIM_ATOM_NAME is the older Vim-specific selection type for X11. Still