printf: short-circuit output when argument to %b includes \c
authorRon Yorston <rmy@pobox.com>
Sun, 31 Jan 2016 21:22:25 +0000 (22:22 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 31 Jan 2016 21:23:05 +0000 (22:23 +0100)
printf wasn't correctly handling \c in an argument to the %b format
specifier.

   printf %bXX OK\\c

returned 'OK\cXX' rather than the expected 'OK'.

function                                             old     new   delta
printf_main                                          886     899     +13

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
coreutils/printf.c

index 3dd43a978205f2ebcbfc3c3f49d7e5e0130264d2..9ee7350d01d0989bfa0add727e8b5eaaf18e7132 100644 (file)
@@ -131,8 +131,8 @@ static double my_xstrtod(const char *arg)
        return result;
 }
 
-/* Handles %b */
-static void print_esc_string(const char *str)
+/* Handles %b; return 1 if output is to be short-circuited by \c */
+static int print_esc_string(const char *str)
 {
        char c;
        while ((c = *str) != '\0') {
@@ -145,6 +145,9 @@ static void print_esc_string(const char *str)
                                        str++;
                                }
                        }
+                       else if (*str == 'c') {
+                               return 1;
+                       }
                        {
                                /* optimization: don't force arg to be on-stack,
                                 * use another variable for that. */
@@ -155,6 +158,8 @@ static void print_esc_string(const char *str)
                }
                putchar(c);
        }
+
+       return 0;
 }
 
 static void print_direc(char *format, unsigned fmt_length,
@@ -280,7 +285,8 @@ static char **print_formatted(char *f, char **argv, int *conv_err)
                        }
                        if (*f == 'b') {
                                if (*argv) {
-                                       print_esc_string(*argv);
+                                       if (print_esc_string(*argv))
+                                               return saved_argv; /* causes main() to exit */
                                        ++argv;
                                }
                                break;