printf: do not print garbage on "%Ld". closes bug 4214.
function old new delta printf_main 633 637 +4 multiconvert 99 79 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-20) Total: -16 bytes
This commit is contained in:
parent
f19817ddc2
commit
5f116629d8
@ -63,11 +63,8 @@ typedef void FAST_FUNC (*converter)(const char *arg, void *result);
|
|||||||
|
|
||||||
static int multiconvert(const char *arg, void *result, converter convert)
|
static int multiconvert(const char *arg, void *result, converter convert)
|
||||||
{
|
{
|
||||||
char s[sizeof(int)*3 + 2];
|
|
||||||
|
|
||||||
if (*arg == '"' || *arg == '\'') {
|
if (*arg == '"' || *arg == '\'') {
|
||||||
sprintf(s, "%d", (unsigned char)arg[1]);
|
arg = utoa((unsigned char)arg[1]);
|
||||||
arg = s;
|
|
||||||
}
|
}
|
||||||
errno = 0;
|
errno = 0;
|
||||||
convert(arg, result);
|
convert(arg, result);
|
||||||
@ -289,10 +286,22 @@ static char **print_formatted(char *f, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Remove size modifiers - "%Ld" would try to printf
|
||||||
|
* long long, we pass long, and it spews garbage */
|
||||||
if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
|
if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
|
||||||
++f;
|
strcpy(f, f + 1);
|
||||||
++direc_length;
|
|
||||||
}
|
}
|
||||||
|
//FIXME: actually, the same happens with bare "%d":
|
||||||
|
//it printfs an int, but we pass long!
|
||||||
|
//What saves us is that on most arches stack slot
|
||||||
|
//is pointer-sized -> long-sized -> ints are promoted to longs
|
||||||
|
// for variadic functions -> printf("%d", int_v) is in reality
|
||||||
|
// indistinqushable from printf("%d", long_v) ->
|
||||||
|
// since printf("%d", int_v) works, printf("%d", long_v) has to work.
|
||||||
|
//But "clean" solution would be to add "l" to d,i,o,x,X.
|
||||||
|
//Probably makes sense to go all the way to "ll" then.
|
||||||
|
//Coreutils support long long-sized arguments.
|
||||||
|
|
||||||
/* needed - try "printf %" without it */
|
/* needed - try "printf %" without it */
|
||||||
if (!strchr("diouxXfeEgGcs", *f)) {
|
if (!strchr("diouxXfeEgGcs", *f)) {
|
||||||
bb_error_msg("%s: invalid format", direc_start);
|
bb_error_msg("%s: invalid format", direc_start);
|
||||||
|
@ -74,6 +74,11 @@ testing "printf understands %ld" \
|
|||||||
"-5\n""0\n" \
|
"-5\n""0\n" \
|
||||||
"" ""
|
"" ""
|
||||||
|
|
||||||
|
testing "printf understands %Ld" \
|
||||||
|
"${bb}printf '%Ld\n' -5 2>&1; echo \$?" \
|
||||||
|
"-5\n""0\n" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
# We are "more correct" here than bash/coreutils: they happily print -2
|
# We are "more correct" here than bash/coreutils: they happily print -2
|
||||||
# as if it is a huge unsigned number
|
# as if it is a huge unsigned number
|
||||||
testing "printf handles %u -N" \
|
testing "printf handles %u -N" \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user