printk: fix printing of long long types

64-bit types were not being handled properly and depending on the
calling convention could result in garbage values being printed.

We still truncate these to 32-bit values, the predominant use-case
is printing timestamp delta values which generally fit in a 32-bit
value. However we are no longer printing random stuff.

Test case for printk() updated appripriately to catch this regression.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-05-30 14:38:11 -07:00 committed by Anas Nashif
commit 5963904e4c
2 changed files with 35 additions and 6 deletions

View file

@ -90,6 +90,7 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
int might_format = 0; /* 1 if encountered a '%' */
enum pad_type padding = PAD_NONE;
int min_width = -1;
int long_ctr = 0;
/* fmt has already been adjusted if needed */
@ -101,6 +102,7 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
might_format = 1;
min_width = -1;
padding = PAD_NONE;
long_ctr = 0;
}
} else {
switch (*fmt) {
@ -124,14 +126,21 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
padding = PAD_SPACE_BEFORE;
}
goto still_might_format;
case 'z':
case 'l':
long_ctr++;
/* Fall through */
case 'z':
case 'h':
/* FIXME: do nothing for these modifiers */
goto still_might_format;
case 'd':
case 'i': {
long d = va_arg(ap, long);
long d;
if (long_ctr < 2) {
d = va_arg(ap, long);
} else {
d = (long)va_arg(ap, long long);
}
if (d < 0) {
out((int)'-', ctx);
@ -143,8 +152,14 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
break;
}
case 'u': {
unsigned long u = va_arg(
ap, unsigned long);
unsigned long u;
if (long_ctr < 2) {
u = va_arg(ap, unsigned long);
} else {
u = (unsigned long)va_arg(ap,
unsigned long long);
}
_printk_dec_ulong(out, ctx, u, padding,
min_width);
break;
@ -158,8 +173,15 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
/* Fall through */
case 'x':
case 'X': {
unsigned long x = va_arg(
ap, unsigned long);
unsigned long x;
if (long_ctr < 2) {
x = va_arg(ap, unsigned long);
} else {
x = (unsigned long)va_arg(ap,
unsigned long long);
}
_printk_hex_ulong(out, ctx, x, padding,
min_width);
break;

View file

@ -25,6 +25,7 @@ char *expected = "22 113 10000 32768 40000 22\n"
"42 42 42 42\n"
"42 42 0042 00000042\n"
"255 42 abcdef 0x0000002a 42\n"
"-1 4294967295 ffffffff\n"
;
@ -61,6 +62,8 @@ void printk_test(void)
{
int count;
printk("%lld %llu %llx",
1LL, -1ULL, -1ULL);
_old_char_out = __printk_get_hook();
__printk_hook_install(ram_console_out);
@ -74,6 +77,7 @@ void printk_test(void)
printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
printk("%u %02u %04u %08u\n", 42, 42, 42, 42);
printk("%-8u%-6d%-4x%-2p%8d\n", 0xFF, 42, 0xABCDEF, (char *)42, 42);
printk("%lld %llu %llx\n", -1LL, -1ULL, -1ULL);
ram_console[pos] = '\0';
zassert_true((strcmp(ram_console, expected) == 0), "printk failed");
@ -103,6 +107,9 @@ void printk_test(void)
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%-8u%-6d%-4x%-2p%8d\n",
0xFF, 42, 0xABCDEF, (char *)42, 42);
count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%lld %llu %llx\n",
-1LL, -1ULL, -1ULL);
ram_console[count] = '\0';
zassert_true((strcmp(ram_console, expected) == 0), "snprintk failed");
}