# HG changeset patch # User Bram Moolenaar # Date 1420642637 -3600 # Node ID 22f95a018b13dc9d8a3246d990a1ea0b5b3a264d # Parent 5cd8162022f070dceee64f27741d224f15ff138c updated for version 7.4.565 Problem: Ranges for arguments, buffers, tabs, etc. are not checked to be valid but limited to the maximum. This can cause the wrong thing to happen. Solution: Give an error for an invalid value. (Marcin Szamotulski) Use windows range for ":wincmd". diff --git a/src/ex_cmds.h b/src/ex_cmds.h --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -1574,7 +1574,7 @@ EX(CMD_winsize, "winsize", ex_winsize, ADDR_LINES), EX(CMD_wincmd, "wincmd", ex_wincmd, NEEDARG|WORD1|RANGE|NOTADR, - ADDR_LINES), + ADDR_WINDOWS), EX(CMD_windo, "windo", ex_listdo, BANG|NEEDARG|EXTRA|NOTRLCOM, ADDR_LINES), diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2161,6 +2161,8 @@ do_one_cmd(cmdlinep, sourcing, break; case ADDR_ARGUMENTS: ea.line2 = curwin->w_arg_idx + 1; + if (ea.line2 > ARGCOUNT) + ea.line2 = ARGCOUNT; break; case ADDR_LOADED_BUFFERS: case ADDR_BUFFERS: @@ -3110,7 +3112,7 @@ find_command(eap, full) * Exceptions: * - the 'k' command can directly be followed by any character. * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r' - * but :sre[wind] is another command, as are :scrip[tnames], + * but :sre[wind] is another command, as are :scr[iptnames], * :scs[cope], :sim[alt], :sig[ns] and :sil[ent]. * - the "d" command can directly be followed by 'l' or 'p' flag. */ @@ -4573,46 +4575,6 @@ get_address(ptr, addr_type, skip, to_oth lnum -= n; else lnum += n; - - switch (addr_type) - { - case ADDR_LINES: - break; - case ADDR_ARGUMENTS: - if (lnum < 0) - lnum = 0; - else if (lnum >= ARGCOUNT) - lnum = ARGCOUNT; - break; - case ADDR_TABS: - if (lnum < 0) - { - lnum = 0; - break; - } - if (lnum >= LAST_TAB_NR) - lnum = LAST_TAB_NR; - break; - case ADDR_WINDOWS: - if (lnum < 0) - { - lnum = 0; - break; - } - if (lnum >= LAST_WIN_NR) - lnum = LAST_WIN_NR; - break; - case ADDR_LOADED_BUFFERS: - case ADDR_BUFFERS: - if (lnum < firstbuf->b_fnum) - { - lnum = firstbuf->b_fnum; - break; - } - if (lnum > lastbuf->b_fnum) - lnum = lastbuf->b_fnum; - break; - } } } while (*cmd == '/' || *cmd == '?'); @@ -4675,17 +4637,65 @@ ex_script_ni(eap) invalid_range(eap) exarg_T *eap; { + buf_T *buf; if ( eap->line1 < 0 || eap->line2 < 0 - || eap->line1 > eap->line2 - || ((eap->argt & RANGE) - && !(eap->argt & NOTADR) - && eap->line2 > curbuf->b_ml.ml_line_count + || eap->line1 > eap->line2) + return (char_u *)_(e_invrange); + + if (eap->argt & RANGE) + { + switch(eap->addr_type) + { + case ADDR_LINES: + if (!(eap->argt & NOTADR) + && eap->line2 > curbuf->b_ml.ml_line_count #ifdef FEAT_DIFF - + (eap->cmdidx == CMD_diffget) -#endif - )) - return (char_u *)_(e_invrange); + + (eap->cmdidx == CMD_diffget) +#endif + ) + return (char_u *)_(e_invrange); + break; + case ADDR_ARGUMENTS: + if (eap->line2 > ARGCOUNT + (!ARGCOUNT)) // add 1 if ARCOUNT is 0 + return (char_u *)_(e_invrange); + break; + case ADDR_BUFFERS: + if (eap->line1 < firstbuf->b_fnum + || eap->line2 > lastbuf->b_fnum) + return (char_u *)_(e_invrange); + break; + case ADDR_LOADED_BUFFERS: + buf = firstbuf; + while (buf->b_ml.ml_mfp == NULL) + { + if (buf->b_next == NULL) + return (char_u *)_(e_invrange); + buf = buf->b_next; + } + if (eap->line1 < buf->b_fnum) + return (char_u *)_(e_invrange); + buf = lastbuf; + while (buf->b_ml.ml_mfp == NULL) + { + if (buf->b_prev == NULL) + return (char_u *)_(e_invrange); + buf = buf->b_prev; + } + if (eap->line2 > buf->b_fnum) + return (char_u *)_(e_invrange); + break; + case ADDR_WINDOWS: + if (eap->line1 < 1 + || eap->line2 > LAST_WIN_NR) + return (char_u *)_(e_invrange); + break; + case ADDR_TABS: + if (eap->line2 > LAST_TAB_NR) + return (char_u *)_(e_invrange); + break; + } + } return NULL; } diff --git a/src/testdir/test62.in b/src/testdir/test62.in --- a/src/testdir/test62.in +++ b/src/testdir/test62.in @@ -13,7 +13,7 @@ STARTTEST :" Open three tab pages and use ":tabdo" :0tabnew :1tabnew -:888tabnew +:$tabnew :tabdo call append(line('$'), 'this is tab page ' . tabpagenr()) :tabclose! 2 :tabrewind diff --git a/src/testdir/test_argument_count.in b/src/testdir/test_argument_count.in --- a/src/testdir/test_argument_count.in +++ b/src/testdir/test_argument_count.in @@ -27,10 +27,9 @@ STARTTEST :1arga c :1arga b :$argu -:+arga d :$arga x :call add(arglists, argv()) -:$-10arga Y +:0arga Y :call add(arglists, argv()) :%argd :call add(arglists, argv()) diff --git a/src/testdir/test_argument_count.ok b/src/testdir/test_argument_count.ok --- a/src/testdir/test_argument_count.ok +++ b/src/testdir/test_argument_count.ok @@ -7,7 +7,7 @@ c a b d a d a -a b c d x -Y a b c d x +a b c x +Y a b c x a f diff --git a/src/testdir/test_close_count.in b/src/testdir/test_close_count.in --- a/src/testdir/test_close_count.in +++ b/src/testdir/test_close_count.in @@ -28,7 +28,7 @@ STARTTEST :new :new :2wincmd w -:-2close! +:-1close! :let buffers = [] :windo call add(buffers, bufnr('%')) :call add(tests, buffers) @@ -61,7 +61,7 @@ STARTTEST :let buffers = [] :windo call add(buffers, bufnr('%')) :call add(tests, buffers) -:9hide +:$hide :let buffers = [] :windo call add(buffers, bufnr('%')) :call add(tests, buffers) diff --git a/src/testdir/test_command_count.in b/src/testdir/test_command_count.in --- a/src/testdir/test_command_count.in +++ b/src/testdir/test_command_count.in @@ -1,8 +1,8 @@ Test for user command counts vim: set ft=vim : STARTTEST +:so tiny.vim :let g:lines = [] -:so tiny.vim :com -range=% RangeLines :call add(g:lines, 'RangeLines '..' '.) :com -range -addr=arguments RangeArguments :call add(g:lines, 'RangeArguments '..' '.) :com -range=% -addr=arguments RangeArgumentsAll :call add(g:lines, 'RangeArgumentsAll '..' '.) @@ -48,6 +48,46 @@ STARTTEST :'<,'>RangeLines :com -range=% -buffer LocalRangeLines :call add(g:lines, 'LocalRangeLines '..' '.) :'<,'>LocalRangeLines +:b1 +ENDTEST + +STARTTEST +:call add(g:lines, '') +:%argd +:arga a b c d +:let v:errmsg = '' +:5argu +:call add(g:lines, '5argu ' . v:errmsg) +:$argu +:call add(g:lines, '4argu ' . expand('%:t')) +:let v:errmsg = '' +:1argu +:call add(g:lines, '1argu ' . expand('%:t')) +:let v:errmsg = '' +:100b +:call add(g:lines, '100b ' . v:errmsg) +:split|split|split|split +:let v:errmsg = '' +:0close +:call add(g:lines, '0close ' . v:errmsg) +:$wincmd w +:$close +:call add(g:lines, '$close ' . winnr()) +:let v:errmsg = '' +:$+close +:call add(g:lines, '$+close ' . v:errmsg) +:$tabe +:call add(g:lines, '$tabe ' . tabpagenr()) +:let v:errmsg = '' +:$+tabe +:call add(g:lines, '$+tabe ' . v:errmsg) +:only! +:e x +:0tabm +:normal 1gt +:call add(g:lines, '0tabm ' . expand('%:t')) +:tabonly! +:only! :e! test.out :call append(0, g:lines) :w|qa! diff --git a/src/testdir/test_command_count.ok b/src/testdir/test_command_count.ok --- a/src/testdir/test_command_count.ok +++ b/src/testdir/test_command_count.ok @@ -17,3 +17,14 @@ RangeTabsAll 1 5 RangeLines 2 5 LocalRangeLines 2 5 +5argu E16: Invalid range +4argu d +1argu a +100b E16: Invalid range +0close E16: Invalid range +$close 4 +$+close E16: Invalid range +$tabe 2 +$+tabe E16: Invalid range +0tabm x + diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 565, +/**/ 564, /**/ 563,