changeset 6472:22f95a018b13 v7.4.565

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".
author Bram Moolenaar <bram@vim.org>
date Wed, 07 Jan 2015 15:57:17 +0100
parents 5cd8162022f0
children 259b0f4f6e76
files src/ex_cmds.h src/ex_docmd.c src/testdir/test62.in src/testdir/test_argument_count.in src/testdir/test_argument_count.ok src/testdir/test_close_count.in src/testdir/test_command_count.in src/testdir/test_command_count.ok src/version.c
diffstat 9 files changed, 120 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- 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),
--- 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;
 }
 
--- 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
--- 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())
--- 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
--- 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)
--- 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 '.<line1>.' '.<line2>)
 :com -range -addr=arguments RangeArguments :call add(g:lines, 'RangeArguments '.<line1>.' '.<line2>)
 :com -range=% -addr=arguments RangeArgumentsAll :call add(g:lines, 'RangeArgumentsAll '.<line1>.' '.<line2>)
@@ -48,6 +48,46 @@ STARTTEST
 :'<,'>RangeLines
 :com -range=% -buffer LocalRangeLines :call add(g:lines, 'LocalRangeLines '.<line1>.' '.<line2>)
 :'<,'>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!
--- 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
+
--- 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,