Skip to content

Commit 3c28533

Browse files
committed
Fix %c with nul character
Fixes #417
1 parent 91953dd commit 3c28533

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

libc/fmt/fmt.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,12 +335,16 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
335335
break;
336336
}
337337
case 'c':
338-
prec = 1;
339-
flags |= FLAGS_PRECISION;
340-
qchar = '\'';
341-
p = charbuf;
342-
charbuf[0] = va_arg(va, int);
343-
goto FormatString;
338+
if ((charbuf[0] = va_arg(va, int))) {
339+
p = charbuf;
340+
qchar = '\'';
341+
flags |= FLAGS_PRECISION;
342+
prec = 1;
343+
goto FormatString;
344+
} else {
345+
__FMT_PUT('\0');
346+
break;
347+
}
344348
case 'm':
345349
p = weaken(strerror) ? weaken(strerror)(lasterr) : "?";
346350
signbit = 0;

test/libc/fmt/fmt_test.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@ TEST(fmt, quoted) {
283283
ASSERT_STREQ("\"hello\" ", gc(xasprintf("%-`*.*s", 10, 5, "hello")));
284284
}
285285

286+
TEST(fmt, nulCharacter) {
287+
char b[3] = {1, 1, 1};
288+
ASSERT_EQ(1, snprintf(0, 0, "%c", 0));
289+
ASSERT_EQ(1, snprintf(b, 3, "%c", 0));
290+
ASSERT_EQ(0, b[0]);
291+
ASSERT_EQ(0, b[1]);
292+
ASSERT_EQ(1, b[2]);
293+
}
294+
286295
TEST(fmt, regress) {
287296
char buf[512];
288297
const char *meth = "GET";

0 commit comments

Comments
 (0)