printk: don't print incorrect 64-bit integers

printk is supposed to be very lean, but should at least not
print garbage values. Now when a 64-bit integral value is
passed in to be printed, 'ERR' will be reported if it doesn't
fit in 32-bits instead of truncating it.

The printk documentation was slightly out of date, this has been
updated.

Fixes: #7179

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-01-17 13:26:51 -08:00 committed by Andrew Boie
commit 970758408b
3 changed files with 52 additions and 15 deletions

View file

@ -33,8 +33,11 @@ extern "C" {
* - character: \%c * - character: \%c
* - percent: \%\% * - percent: \%\%
* *
* No other conversion specification capabilities are supported, such as flags, * Field width (with or without leading zeroes) are supported.
* field width, precision, or length attributes. * Length attributes such as 'h' and 'l' are supported. However,
* integral values with %lld and %lli are only printed if they fit in 32 bits,
* otherwise 'ERR' is printed. Full 64-bit values may be printed with %llx.
* Flags and precision attributes are not supported.
* *
* @param fmt Format string. * @param fmt Format string.
* @param ... Optional list of format arguments. * @param ... Optional list of format arguments.

View file

@ -82,6 +82,13 @@ void *__printk_get_hook(void)
return _char_out; return _char_out;
} }
static void print_err(out_func_t out, void *ctx)
{
out('E', ctx);
out('R', ctx);
out('R', ctx);
}
/** /**
* @brief Printk internals * @brief Printk internals
* *
@ -141,11 +148,25 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
goto still_might_format; goto still_might_format;
case 'd': case 'd':
case 'i': { case 'i': {
long d; s32_t d;
if (long_ctr < 2) {
d = va_arg(ap, long); if (long_ctr == 0) {
d = va_arg(ap, int);
} else if (long_ctr == 1) {
long ld = va_arg(ap, long);
if (ld > INT32_MAX || ld < INT32_MIN) {
print_err(out, ctx);
break;
}
d = (s32_t)ld;
} else { } else {
d = (long)va_arg(ap, long long); long long lld = va_arg(ap, long long);
if (lld > INT32_MAX ||
lld < INT32_MIN) {
print_err(out, ctx);
break;
}
d = (s32_t)lld;
} }
if (d < 0) { if (d < 0) {
@ -158,14 +179,27 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
break; break;
} }
case 'u': { case 'u': {
unsigned long u; u32_t u;
if (long_ctr < 2) { if (long_ctr == 0) {
u = va_arg(ap, unsigned long); u = va_arg(ap, unsigned int);
} else { } else if (long_ctr == 1) {
u = (unsigned long)va_arg(ap, long lu = va_arg(ap, unsigned long);
unsigned long long); if (lu > INT32_MAX) {
print_err(out, ctx);
break;
} }
u = (u32_t)lu;
} else {
unsigned long long llu =
va_arg(ap, unsigned long long);
if (llu > INT32_MAX) {
print_err(out, ctx);
break;
}
u = (u32_t)llu;
}
_printk_dec_ulong(out, ctx, u, padding, _printk_dec_ulong(out, ctx, u, padding,
min_width); min_width);
break; break;

View file

@ -25,7 +25,7 @@ char *expected = "22 113 10000 32768 40000 22\n"
"42 42 42 42\n" "42 42 42 42\n"
"42 42 0042 00000042\n" "42 42 0042 00000042\n"
"255 42 abcdef 0x0000002a 42\n" "255 42 abcdef 0x0000002a 42\n"
"-1 4294967295 ffffffffffffffff\n" "ERR -1 ERR ffffffffffffffff\n"
; ;
@ -86,7 +86,7 @@ void test_printk(void)
printk("%u %2u %4u %8u\n", 42, 42, 42, 42); printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
printk("%u %02u %04u %08u\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("%-8u%-6d%-4x%-2p%8d\n", 0xFF, 42, 0xABCDEF, (char *)42, 42);
printk("%lld %llu %llx\n", -1LL, -1ULL, -1ULL); printk("%lld %lld %llu %llx\n", 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
ram_console[pos] = '\0'; ram_console[pos] = '\0';
zassert_true((strcmp(ram_console, expected) == 0), "printk failed"); zassert_true((strcmp(ram_console, expected) == 0), "printk failed");
@ -117,8 +117,8 @@ void test_printk(void)
"%-8u%-6d%-4x%-2p%8d\n", "%-8u%-6d%-4x%-2p%8d\n",
0xFF, 42, 0xABCDEF, (char *)42, 42); 0xFF, 42, 0xABCDEF, (char *)42, 42);
count += snprintk(ram_console + count, sizeof(ram_console) - count, count += snprintk(ram_console + count, sizeof(ram_console) - count,
"%lld %llu %llx\n", "%lld %lld %llu %llx\n",
-1LL, -1ULL, -1ULL); 0xFFFFFFFFFULL, -1LL, -1ULL, -1ULL);
ram_console[count] = '\0'; ram_console[count] = '\0';
zassert_true((strcmp(ram_console, expected) == 0), "snprintk failed"); zassert_true((strcmp(ram_console, expected) == 0), "snprintk failed");
} }