Skip to content

Commit caca8c0

Browse files
Andrew BoieAnas Nashif
authored andcommitted
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 <[email protected]>
1 parent 7b5506d commit caca8c0

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

misc/printk.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
9090
int might_format = 0; /* 1 if encountered a '%' */
9191
enum pad_type padding = PAD_NONE;
9292
int min_width = -1;
93+
int long_ctr = 0;
9394

9495
/* fmt has already been adjusted if needed */
9596

@@ -101,6 +102,7 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
101102
might_format = 1;
102103
min_width = -1;
103104
padding = PAD_NONE;
105+
long_ctr = 0;
104106
}
105107
} else {
106108
switch (*fmt) {
@@ -124,14 +126,21 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
124126
padding = PAD_SPACE_BEFORE;
125127
}
126128
goto still_might_format;
127-
case 'z':
128129
case 'l':
130+
long_ctr++;
131+
/* Fall through */
132+
case 'z':
129133
case 'h':
130134
/* FIXME: do nothing for these modifiers */
131135
goto still_might_format;
132136
case 'd':
133137
case 'i': {
134-
long d = va_arg(ap, long);
138+
long d;
139+
if (long_ctr < 2) {
140+
d = va_arg(ap, long);
141+
} else {
142+
d = (long)va_arg(ap, long long);
143+
}
135144

136145
if (d < 0) {
137146
out((int)'-', ctx);
@@ -143,8 +152,14 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
143152
break;
144153
}
145154
case 'u': {
146-
unsigned long u = va_arg(
147-
ap, unsigned long);
155+
unsigned long u;
156+
157+
if (long_ctr < 2) {
158+
u = va_arg(ap, unsigned long);
159+
} else {
160+
u = (unsigned long)va_arg(ap,
161+
unsigned long long);
162+
}
148163
_printk_dec_ulong(out, ctx, u, padding,
149164
min_width);
150165
break;
@@ -158,8 +173,15 @@ void _vprintk(out_func_t out, void *ctx, const char *fmt, va_list ap)
158173
/* Fall through */
159174
case 'x':
160175
case 'X': {
161-
unsigned long x = va_arg(
162-
ap, unsigned long);
176+
unsigned long x;
177+
178+
if (long_ctr < 2) {
179+
x = va_arg(ap, unsigned long);
180+
} else {
181+
x = (unsigned long)va_arg(ap,
182+
unsigned long long);
183+
}
184+
163185
_printk_hex_ulong(out, ctx, x, padding,
164186
min_width);
165187
break;

tests/kernel/common/src/printk.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ char *expected = "22 113 10000 32768 40000 22\n"
2525
"42 42 42 42\n"
2626
"42 42 0042 00000042\n"
2727
"255 42 abcdef 0x0000002a 42\n"
28+
"-1 4294967295 ffffffff\n"
2829
;
2930

3031

@@ -61,6 +62,8 @@ void printk_test(void)
6162
{
6263
int count;
6364

65+
printk("%lld %llu %llx",
66+
1LL, -1ULL, -1ULL);
6467
_old_char_out = __printk_get_hook();
6568
__printk_hook_install(ram_console_out);
6669

@@ -74,6 +77,7 @@ void printk_test(void)
7477
printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
7578
printk("%u %02u %04u %08u\n", 42, 42, 42, 42);
7679
printk("%-8u%-6d%-4x%-2p%8d\n", 0xFF, 42, 0xABCDEF, (char *)42, 42);
80+
printk("%lld %llu %llx\n", -1LL, -1ULL, -1ULL);
7781

7882
ram_console[pos] = '\0';
7983
zassert_true((strcmp(ram_console, expected) == 0), "printk failed");
@@ -103,6 +107,9 @@ void printk_test(void)
103107
count += snprintk(ram_console + count, sizeof(ram_console) - count,
104108
"%-8u%-6d%-4x%-2p%8d\n",
105109
0xFF, 42, 0xABCDEF, (char *)42, 42);
110+
count += snprintk(ram_console + count, sizeof(ram_console) - count,
111+
"%lld %llu %llx\n",
112+
-1LL, -1ULL, -1ULL);
106113
ram_console[count] = '\0';
107114
zassert_true((strcmp(ram_console, expected) == 0), "snprintk failed");
108115
}

0 commit comments

Comments
 (0)