diff --git a/src/printf.c b/src/printf.c index 37844f14a..442935705 100644 --- a/src/printf.c +++ b/src/printf.c @@ -454,14 +454,23 @@ print_formatted (char const *format, int argc, char **argv) #define GET_CURR_ARG(POS) \ do { \ - char *arge; \ - intmax_t arg = POS==3 ? 0 : strtoimax (f, &arge, 10); \ - if (0 < arg && arg <= INT_MAX && *arge == '$') \ + intmax_t arg = 0; \ + size_t argl; \ + /* Check with strspn() first to avoid spaces etc. \ + This also avoids any locale ambiguities. */ \ + if (POS != 3 && (argl = strspn (f, "0123456789")) \ + && f[argl] == '$') \ + { \ + errno = 0; \ + arg = strtoimax (f, NULL, 10); \ + if (errno) \ + arg = 0; \ + } \ + if (1 <= arg && arg <= INT_MAX) \ /* Process indexed %i$ format. */ \ - /* Note '$' comes before any flags. */ \ { \ SET_CURR_ARG (arg - 1); \ - f = arge + 1; \ + f += argl + 1; \ if (POS == 0) \ direc_arg = arg - 1; \ } \ diff --git a/tests/printf/printf-indexed.sh b/tests/printf/printf-indexed.sh index d0f799ab1..5d63d68f8 100755 --- a/tests/printf/printf-indexed.sh +++ b/tests/printf/printf-indexed.sh @@ -75,19 +75,28 @@ printf_check ' 1' '%2$*1$d\n' 4 1 # Indexed arg, and sequential width printf_check ' 1' '%2$*d\n' 4 1 -# Flags come after $ (0 is not a flag here): +# Flags come after $ (0 is not a flag here but allowed): printf_check ' 1' '%01$4d\n' 1 # Flags come after $ (0 is a flag here): printf_check '0001' '%1$0*2$d\n' 1 4 # Flags come after $ (-2 not taken as a valid index here): printf_check_err 'printf: %-2$: invalid conversion specification' \ '%-2$s %1$s\n' A B +# Flags come after $ (' ' is not allowed as part of number here) +printf_check_err 'printf: % 2$: invalid conversion specification' \ + '% 2$s %1$s\n' A B # Ensure only base 10 numbers are accepted printf_check_err "printf: 'A': expected a numeric value" \ '%0x2$s %2$s\n' A B +# Ensure empty numbers are rejected +printf_check_err 'printf: %$: invalid conversion specification' \ + '%$d\n' 1 # Verify int limits (avoiding comparisons with argc etc.) printf_check_err "printf: %${INT_OFLOW}\$: invalid conversion specification" \ "%${INT_OFLOW}\$d\n" 1 +# Verify intmax limits, ensuring overflow detected +printf_check_err "printf: %${INTMAX_OFLOW}\$: invalid conversion specification" \ + "%${INTMAX_OFLOW}\$d\n" 1 Exit $fail