# HG changeset patch # User Christian Brabandt # Date 1710440103 -3600 # Node ID 0adcad161c464c4dde58cf59bd8ed08234664738 # Parent 8b94adf4474a4688ad0289ed46948d91be91fbef patch 9.1.0181: no overflow check for string formatting Commit: https://github.com/vim/vim/commit/c35fc03dbd47582b256776fb11f11d8ceb24f8f0 Author: Christ van Willegen Date: Thu Mar 14 18:30:41 2024 +0100 patch 9.1.0181: no overflow check for string formatting Problem: no overflow check for string formatting Solution: Check message formatting function for overflow. (Chris van Willegen) closes: #13799 Signed-off-by: Christ van Willegen Signed-off-by: Christian Brabandt diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1,4 +1,4 @@ -*builtin.txt* For Vim version 9.1. Last change: 2024 Mar 13 +*builtin.txt* For Vim version 9.1. Last change: 2024 Mar 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -7105,6 +7105,9 @@ printf({fmt}, {expr1} ...) *printf()* echo printf("%1$*2$.*3$f", 1.4142135, 6, 2) < 1.41 + You will get an overflow error |E1510|, when the field-width + or precision will result in a string longer than 6400 chars. + *E1500* You cannot mix positional and non-positional arguments: > echo printf("%s%1$s", "One", "Two") diff --git a/src/strings.c b/src/strings.c --- a/src/strings.c +++ b/src/strings.c @@ -2468,6 +2468,55 @@ adjust_types( return OK; } + static void +format_overflow_error(const char *pstart) +{ + size_t arglen = 0; + char *argcopy = NULL; + const char *p = pstart; + + while (VIM_ISDIGIT((int)(*p))) + ++p; + + arglen = p - pstart; + argcopy = ALLOC_CLEAR_MULT(char, arglen + 1); + if (argcopy != NULL) + { + strncpy(argcopy, pstart, arglen); + semsg(_( e_val_too_large), argcopy); + free(argcopy); + } + else + semsg(_(e_out_of_memory_allocating_nr_bytes), arglen); +} + +#define MAX_ALLOWED_STRING_WIDTH 6400 + + static int +get_unsigned_int( + const char *pstart, + const char **p, + unsigned int *uj) +{ + *uj = **p - '0'; + ++*p; + + while (VIM_ISDIGIT((int)(**p)) && *uj < MAX_ALLOWED_STRING_WIDTH) + { + *uj = 10 * *uj + (unsigned int)(**p - '0'); + ++*p; + } + + if (*uj > MAX_ALLOWED_STRING_WIDTH) + { + format_overflow_error(pstart); + return FAIL; + } + + return OK; +} + + static int parse_fmt_types( const char ***ap_types, @@ -2511,6 +2560,7 @@ parse_fmt_types( // variable for positional arg int pos_arg = -1; const char *ptype = NULL; + const char *pstart = p+1; p++; // skip '%' @@ -2531,10 +2581,11 @@ parse_fmt_types( } // Positional argument - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + unsigned int uj; + + if (get_unsigned_int(pstart, &p, &uj) == FAIL) + goto error; + pos_arg = uj; any_pos = 1; @@ -2571,10 +2622,10 @@ parse_fmt_types( if (VIM_ISDIGIT((int)(*p))) { // Positional argument field width - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + unsigned int uj; + + if (get_unsigned_int(arg + 1, &p, &uj) == FAIL) + goto error; if (*p != '$') { @@ -2601,10 +2652,11 @@ parse_fmt_types( { // size_t could be wider than unsigned int; make sure we treat // argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + const char *digstart = p; + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; if (*p == '$') { @@ -2625,10 +2677,10 @@ parse_fmt_types( if (VIM_ISDIGIT((int)(*p))) { // Parse precision - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + unsigned int uj; + + if (get_unsigned_int(arg + 1, &p, &uj) == FAIL) + goto error; if (*p == '$') { @@ -2656,10 +2708,11 @@ parse_fmt_types( { // size_t could be wider than unsigned int; make sure we // treat argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + const char *digstart = p; + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; if (*p == '$') { @@ -2968,10 +3021,12 @@ vim_vsnprintf_typval( if (*ptype == '$') { // Positional argument - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + const char *digstart = p; + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; + pos_arg = uj; ++p; @@ -3002,16 +3057,18 @@ vim_vsnprintf_typval( if (*p == '*') { int j; + const char *digstart = p + 1; p++; if (VIM_ISDIGIT((int)(*p))) { // Positional argument field width - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; + arg_idx = uj; ++p; @@ -3025,6 +3082,12 @@ vim_vsnprintf_typval( &arg_cur, fmt), va_arg(ap, int)); + if (j > MAX_ALLOWED_STRING_WIDTH) + { + format_overflow_error(digstart); + goto error; + } + if (j >= 0) min_field_width = j; else @@ -3037,10 +3100,18 @@ vim_vsnprintf_typval( { // size_t could be wider than unsigned int; make sure we treat // argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + const char *digstart = p; + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; + + if (uj > MAX_ALLOWED_STRING_WIDTH) + { + format_overflow_error(digstart); + goto error; + } + min_field_width = uj; } @@ -3054,25 +3125,35 @@ vim_vsnprintf_typval( { // size_t could be wider than unsigned int; make sure we // treat argument like common implementations do - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + const char *digstart = p; + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; + + if (uj > MAX_ALLOWED_STRING_WIDTH) + { + format_overflow_error(digstart); + goto error; + } + precision = uj; } else if (*p == '*') { int j; + const char *digstart = p; p++; if (VIM_ISDIGIT((int)(*p))) { // positional argument - unsigned int uj = *p++ - '0'; - - while (VIM_ISDIGIT((int)(*p))) - uj = 10 * uj + (unsigned int)(*p++ - '0'); + unsigned int uj; + + if (get_unsigned_int(digstart, &p, &uj) == FAIL) + goto error; + arg_idx = uj; ++p; @@ -3086,6 +3167,12 @@ vim_vsnprintf_typval( &arg_cur, fmt), va_arg(ap, int)); + if (j > MAX_ALLOWED_STRING_WIDTH) + { + format_overflow_error(digstart); + goto error; + } + if (j >= 0) precision = j; else @@ -3873,6 +3960,7 @@ vim_vsnprintf_typval( if (tvs != NULL && tvs[num_posarg != 0 ? num_posarg : arg_idx - 1].v_type != VAR_UNKNOWN) emsg(_(e_too_many_arguments_to_printf)); +error: vim_free((char*)ap_types); va_end(ap); diff --git a/src/testdir/test_format.vim b/src/testdir/test_format.vim --- a/src/testdir/test_format.vim +++ b/src/testdir/test_format.vim @@ -105,67 +105,6 @@ func Test_printf_pos_misc() END call v9.CheckLegacyAndVim9Success(lines) - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") - call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") - - call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") - call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") - 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:") endfunc func Test_printf_pos_float() @@ -287,8 +226,6 @@ func Test_printf_pos_float() call assert_equal('nan', printf('%1$S', -0.0 / 0.0)) END call v9.CheckLegacyAndVim9Success(lines) - - call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') endfunc func Test_printf_pos_errors() @@ -299,6 +236,111 @@ func Test_printf_pos_errors() call v9.CheckLegacyAndVim9Failure(['echo printf("%1$s")'], 'E1503:') call v9.CheckLegacyAndVim9Failure(['echo printf("%1$d", 1.2)'], 'E805:') call v9.CheckLegacyAndVim9Failure(['echo printf("%1$f")'], 'E1503:') + + call v9.CheckLegacyAndVim9Failure(['echo printf("%f", "a")'], 'E807:') + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 1, 3, 4)"], "E767:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$*1$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$.*1$d%d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%d%2$.*1$d', 1, 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$%')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$_')"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*2$d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*.*1$d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*d', 3)"], "E1500:") + call v9.CheckLegacyAndVim9Failure(["call printf('%*1$.*1$d', 3)"], "E1500:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$d', 3, 3)"], "E1501:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$d %1$ld', 3, 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$*1$d', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %2$*1$d', 3, 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$ld', 3)"], "E1502:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*1$ld', 3)"], "E1502:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d%2$d', 3)"], "E1503:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$d %1$s', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$s', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$f', 3.0)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$d %1$ld', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$p %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$f %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$llud %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$lld %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$s %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$c %1$d', 3)"], "E1504:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$ld %1$d', 3)"], "E1504:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$.2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%01$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%01$0d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3.*2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.2$d', 3)"], "E1505:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*3$.*2d', 3)"], "E1505:") + 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('%.123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.987654321d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.987654321d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.5d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.987654321d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.987654321d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$5.*123456789$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$987654321.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$123456789.*987654321$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$5.*987654321$d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*123456789d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*987654321$.*1$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*123456789$.*987654321$d', 5)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%123456789$*1$.*987654321$d', 5)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*1$d', 5, 9999)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*1$.*2$d', 5, 9999)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*3$.*1$d', 5, 9123, 9321)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$.*3$d', 5, 9123, 9321)"], "E1510:") + call v9.CheckLegacyAndVim9Failure(["call printf('%2$*1$.*3$d', 5, 9123, 9312)"], "E1510:") + + call v9.CheckLegacyAndVim9Failure(["call printf('%1$*2$d', 5, 9999)"], "E1510:") endfunc func Test_printf_pos_64bit() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 181, +/**/ 180, /**/ 179,