]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1971: crash with invalid positional argument 0 in printf()
authorChristian Brabandt <cb@256bit.org>
Thu, 11 Dec 2025 19:51:03 +0000 (20:51 +0100)
committerChristian Brabandt <cb@256bit.org>
Thu, 11 Dec 2025 19:51:03 +0000 (20:51 +0100)
Problem:  crash with invalid positional argument 0 in printf()
Solution: Reject positional arguments <= 0.

closes: #18898

Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/builtin.txt
src/strings.c
src/testdir/test_format.vim

index 3ac3d8a33e1f466e61735f5955a976d0a8002a38..5b143cda8ab15feef7f08dda1cebcc82fc74bf33 100644 (file)
@@ -1,4 +1,4 @@
-*builtin.txt*  For Vim version 9.1.  Last change: 2025 Dec 10
+*builtin.txt*  For Vim version 9.1.  Last change: 2025 Dec 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -8336,24 +8336,24 @@ printf({fmt}, {expr1} ...)                              *printf()*
 
                                                        *E1502*
                You can re-use a [field-width] (or [precision]) argument: >
-                   echo printf("%1$d at width %2$d is: %01$*2$d", 1, 2)
+                   echo printf("%1$d at width %2$d is: %1$0*2$d", 1, 2)
 <                  1 at width 2 is: 01
 
                However, you can't use it as a different type: >
-                   echo printf("%1$d at width %2$ld is: %01$*2$d", 1, 2)
+                   echo printf("%1$d at width %2$ld is: %1$0*2$d", 1, 2)
 <                  E1502: Positional argument 2 used as field width reused as
                    different type: long int/int
 
                                                        *E1503*
                When a positional argument is used, but not the correct number
                or arguments is given, an error is raised: >
-                   echo printf("%1$d at width %2$d is: %01$*2$.*3$d", 1, 2)
+                   echo printf("%1$d at width %2$d is: %1$0*2$.*3$d", 1, 2)
 <                  E1503: Positional argument 3 out of bounds: %1$d at width
-                   %2$d is: %01$*2$.*3$d
+                   %2$d is: %1$0*2$.*3$d
 
                Only the first error is reported: >
-                   echo printf("%01$*2$.*3$d %4$d", 1, 2)
-<                  E1503: Positional argument 3 out of bounds: %01$*2$.*3$d
+                   echo printf("%1$0*2$.*3$d %4$d", 1, 2)
+<                  E1503: Positional argument 3 out of bounds: %1$0*2$.*3$d
                    %4$d
 
                                                        *E1504*
index edf9057f0c020ebe99198a8b00a1218126316de6..8bcd38a8fa29c988084d37754e7be779d480c7a4 100644 (file)
@@ -2843,6 +2843,12 @@ adjust_types(
     int *num_posarg,
     const char *type)
 {
+    if (arg <= 0)
+    {
+       semsg(_( e_invalid_format_specifier_str), type);
+       return FAIL;
+    }
+
     if (*ap_types == NULL || *num_posarg < arg)
     {
        int         idx;
@@ -2876,7 +2882,8 @@ adjust_types(
            {
                switch (pt[0])
                {
-                   case 'd': case 'i': break;
+                   case 'd':
+                   case 'i': break;
                    default:
                        semsg(_(e_positional_num_field_spec_reused_str_str), arg, format_typename((*ap_types)[arg - 1]), format_typename(type));
                        return FAIL;
index b192938d404d0b4ae181f55ebfddb72c00f6c6b7..b7c8b121a4863f2f205c940e6b0a55f47dbecc67 100644 (file)
@@ -299,6 +299,8 @@ func Test_printf_pos_errors()
   call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.5d', 5)"], "E1505:")
   call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.1$d', 5)"], "E1505:")
   call v9.CheckLegacyAndVim9Failure(["call printf('%1$1$.1$d', 5)"], "E1505:")
+  call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*0$s')"], "E1505:")
+  call v9.CheckLegacyAndVim9Failure(["call printf('%*0$s')"], "E1505:")
 
   call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789$d', 5)"], "E1510:")
   call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789d', 5)"], "E1510:")