# HG changeset patch # User Christian Brabandt # Date 1693755005 -7200 # Node ID 7bc10151ce812e799d8b56ab3f17a560205cbf08 # Parent 288d4aa3e263cc253c253fbe761ec09a3f3bb708 patch 9.0.1856: issues with formatting positional arguments Commit: https://github.com/vim/vim/commit/aa90d4f031f73a34aaef5746931ea746849a2231 Author: Christ van Willegen Date: Sun Sep 3 17:22:37 2023 +0200 patch 9.0.1856: issues with formatting positional arguments Problem: issues with formatting positional arguments Solution: fix them, add tests and documentation closes: #12140 closes: #12985 Signed-off-by: Christian Brabandt Co-authored-by: Christ van Willegen Tentatively fix message_test. Check NULL ptr. diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -6707,8 +6707,13 @@ printf({fmt}, {expr1} ...) *printf()* a conversion is wider than the field width, the field is expanded to contain the conversion result. The 'h' modifier indicates the argument is 16 bits. - The 'l' modifier indicates the argument is 32 bits. - The 'L' modifier indicates the argument is 64 bits. + The 'l' modifier indicates the argument is a long + integer. The size will be 32 bits or 64 bits + depending on your platform. + The "ll" modifier indicates the argument is 64 bits. + The b and B conversion specifiers never take a width + modifier and always assume their argument is a 64 bit + integer. Generally, these modifiers are not useful. They are ignored when type is known from the argument. diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -3511,5 +3511,7 @@ EXTERN char e_member_str_type_mismatch_e INIT(= N_("E1406: Member \"%s\": type mismatch, expected %s but got %s")); EXTERN char e_method_str_type_mismatch_expected_str_but_got_str[] INIT(= N_("E1407: Member \"%s\": type mismatch, expected %s but got %s")); +EXTERN char e_aptypes_is_null_str_nr[] + INIT(= "E1408: Internal error: ap_types or ap_types[idx] is NULL: %d: %s"); // E1371 - E1399 unused diff --git a/src/message_test.c b/src/message_test.c --- a/src/message_test.c +++ b/src/message_test.c @@ -40,6 +40,7 @@ char *fmt_012p = "%012p"; char *fmt_5S = "%5S"; char *fmt_06b = "%06b"; char *fmt_06pb = "%1$0.*2$b"; +char *fmt_06pb2 = "%2$0*1$b"; char *fmt_212s = "%2$s %1$s %2$s"; char *fmt_21s = "%2$s %1$s"; @@ -442,6 +443,11 @@ test_vim_snprintf_positional(void) assert(bsize == 0 || STRNCMP(buf, "deadbeef", bsize_int) == 0); assert(bsize == 0 || buf[MIN(n, bsize_int)] == '\0'); + n = vim_snprintf(buf, bsize, fmt_06pb2, 6, (uvarnumber_T)12); + assert(n == 6); + assert(bsize == 0 || STRNCMP(buf, "001100", bsize_int) == 0); + assert(bsize == 0 || buf[MIN(n, bsize_int)] == '\0'); + n = vim_snprintf(buf, bsize, fmt_06pb, (uvarnumber_T)12, 6); assert(n == 6); assert(bsize == 0 || STRNCMP(buf, "001100", bsize_int) == 0); diff --git a/src/strings.c b/src/strings.c --- a/src/strings.c +++ b/src/strings.c @@ -2251,8 +2251,7 @@ enum */ static int format_typeof( - const char *type, - int usetvs UNUSED) + const char *type) { // allowed values: \0, h, l, L char length_modifier = '\0'; @@ -2285,18 +2284,6 @@ format_typeof( default: break; } -# if defined(FEAT_EVAL) - if (usetvs) - { - switch (fmt_spec) - { - case 'd': case 'u': case 'o': case 'x': case 'X': - if (length_modifier == '\0') - length_modifier = 'L'; - } - } -# endif - // get parameter value, do initial processing switch (fmt_spec) { @@ -2330,7 +2317,7 @@ format_typeof( if (fmt_spec == 'p') return TYPE_POINTER; else if (fmt_spec == 'b' || fmt_spec == 'B') - return TYPE_UNSIGNEDINT; + return TYPE_UNSIGNEDLONGLONGINT; else if (fmt_spec == 'd') { // signed @@ -2379,7 +2366,7 @@ format_typeof( format_typename( const char *type) { - switch (format_typeof(type, FALSE)) + switch (format_typeof(type)) { case TYPE_INT: return _(typename_int); @@ -2467,7 +2454,7 @@ adjust_types( } else { - if (format_typeof(type, FALSE) != format_typeof((*ap_types)[arg - 1], FALSE)) + if (format_typeof(type) != format_typeof((*ap_types)[arg - 1])) { semsg(_( e_positional_arg_num_type_inconsistent_str_str), arg, format_typename(type), format_typename((*ap_types)[arg - 1])); return FAIL; @@ -2784,7 +2771,8 @@ skip_to_arg( va_list ap_start, va_list *ap, int *arg_idx, - int *arg_cur) + int *arg_cur, + const char *fmt) { int arg_min = 0; @@ -2809,9 +2797,17 @@ skip_to_arg( for (*arg_cur = arg_min; *arg_cur < *arg_idx - 1; ++*arg_cur) { - const char *p = ap_types[*arg_cur]; - - int fmt_type = format_typeof(p, TRUE); + const char *p; + + if (ap_types == NULL || ap_types[*arg_cur] == NULL) + { + semsg(e_aptypes_is_null_str_nr, fmt, *arg_cur); + return; + } + + p = ap_types[*arg_cur]; + + int fmt_type = format_typeof(p); // get parameter value, do initial processing switch (fmt_type) @@ -3024,7 +3020,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, int)); if (j >= 0) @@ -3084,7 +3081,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, int)); if (j >= 0) @@ -3157,7 +3155,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, int)); // standard demands unsigned char @@ -3172,7 +3171,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, char *)); if (str_arg == NULL) @@ -3269,7 +3269,8 @@ vim_vsnprintf_typval( tvs != NULL ? (void *)tv_str(tvs, &arg_idx, NULL) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, void *)); if (ptr_arg != NULL) @@ -3282,7 +3283,8 @@ vim_vsnprintf_typval( tvs != NULL ? (uvarnumber_T)tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, uvarnumber_T)); if (bin_arg != 0) @@ -3300,7 +3302,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, int)); if (int_arg > 0) @@ -3313,7 +3316,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, long int)); if (long_arg > 0) @@ -3326,7 +3330,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, varnumber_T)); if (llong_arg > 0) @@ -3348,7 +3353,8 @@ vim_vsnprintf_typval( tvs != NULL ? (unsigned) tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, unsigned int)); if (uint_arg != 0) @@ -3360,7 +3366,8 @@ vim_vsnprintf_typval( tvs != NULL ? (unsigned long) tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, unsigned long int)); if (ulong_arg != 0) @@ -3372,7 +3379,8 @@ vim_vsnprintf_typval( tvs != NULL ? (uvarnumber_T) tv_nr(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, uvarnumber_T)); if (ullong_arg != 0) @@ -3574,7 +3582,8 @@ vim_vsnprintf_typval( # if defined(FEAT_EVAL) tvs != NULL ? tv_float(tvs, &arg_idx) : # endif - (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, &arg_cur), + (skip_to_arg(ap_types, ap_start, &ap, &arg_idx, + &arg_cur, fmt), va_arg(ap, double)); abs_f = f < 0 ? -f : f; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -700,6 +700,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1856, +/**/ 1855, /**/ 1854,