diff options
-rw-r--r-- | coreutils/printf.c | 21 | ||||
-rwxr-xr-x | testsuite/printf.tests | 5 |
2 files changed, 20 insertions, 6 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c index ca035cc48..7f6235a87 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -63,11 +63,8 @@ typedef void FAST_FUNC (*converter)(const char *arg, void *result); | |||
63 | 63 | ||
64 | static int multiconvert(const char *arg, void *result, converter convert) | 64 | static int multiconvert(const char *arg, void *result, converter convert) |
65 | { | 65 | { |
66 | char s[sizeof(int)*3 + 2]; | ||
67 | |||
68 | if (*arg == '"' || *arg == '\'') { | 66 | if (*arg == '"' || *arg == '\'') { |
69 | sprintf(s, "%d", (unsigned char)arg[1]); | 67 | arg = utoa((unsigned char)arg[1]); |
70 | arg = s; | ||
71 | } | 68 | } |
72 | errno = 0; | 69 | errno = 0; |
73 | convert(arg, result); | 70 | convert(arg, result); |
@@ -289,10 +286,22 @@ static char **print_formatted(char *f, char **argv) | |||
289 | } | 286 | } |
290 | } | 287 | } |
291 | } | 288 | } |
289 | /* Remove size modifiers - "%Ld" would try to printf | ||
290 | * long long, we pass long, and it spews garbage */ | ||
292 | if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') { | 291 | if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') { |
293 | ++f; | 292 | strcpy(f, f + 1); |
294 | ++direc_length; | ||
295 | } | 293 | } |
294 | //FIXME: actually, the same happens with bare "%d": | ||
295 | //it printfs an int, but we pass long! | ||
296 | //What saves us is that on most arches stack slot | ||
297 | //is pointer-sized -> long-sized -> ints are promoted to longs | ||
298 | // for variadic functions -> printf("%d", int_v) is in reality | ||
299 | // indistinqushable from printf("%d", long_v) -> | ||
300 | // since printf("%d", int_v) works, printf("%d", long_v) has to work. | ||
301 | //But "clean" solution would be to add "l" to d,i,o,x,X. | ||
302 | //Probably makes sense to go all the way to "ll" then. | ||
303 | //Coreutils support long long-sized arguments. | ||
304 | |||
296 | /* needed - try "printf %" without it */ | 305 | /* needed - try "printf %" without it */ |
297 | if (!strchr("diouxXfeEgGcs", *f)) { | 306 | if (!strchr("diouxXfeEgGcs", *f)) { |
298 | bb_error_msg("%s: invalid format", direc_start); | 307 | bb_error_msg("%s: invalid format", direc_start); |
diff --git a/testsuite/printf.tests b/testsuite/printf.tests index a5c71ec9d..f9d1decae 100755 --- a/testsuite/printf.tests +++ b/testsuite/printf.tests | |||
@@ -74,6 +74,11 @@ testing "printf understands %ld" \ | |||
74 | "-5\n""0\n" \ | 74 | "-5\n""0\n" \ |
75 | "" "" | 75 | "" "" |
76 | 76 | ||
77 | testing "printf understands %Ld" \ | ||
78 | "${bb}printf '%Ld\n' -5 2>&1; echo \$?" \ | ||
79 | "-5\n""0\n" \ | ||
80 | "" "" | ||
81 | |||
77 | # We are "more correct" here than bash/coreutils: they happily print -2 | 82 | # We are "more correct" here than bash/coreutils: they happily print -2 |
78 | # as if it is a huge unsigned number | 83 | # as if it is a huge unsigned number |
79 | testing "printf handles %u -N" \ | 84 | testing "printf handles %u -N" \ |