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_docmd.c b/src/ex_docmd.c
index b37c6ed..3276abf 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2161,6 +2161,8 @@
 		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 @@
      * 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 @@
 		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 @@
 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
-#ifdef FEAT_DIFF
-			+ (eap->cmdidx == CMD_diffget)
-#endif
-		))
+	    || 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);
+		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;
 }