diff --git a/libc/stdio/fmt.c b/libc/stdio/fmt.c index a866b196f..6f42e9b39 100644 --- a/libc/stdio/fmt.c +++ b/libc/stdio/fmt.c @@ -1073,6 +1073,9 @@ int __fmt(void *fn, void *arg, const char *format, va_list va, int *wrote) { } break; } + case 'C': + signbit = 63; + // fallthrough case 'c': if ((charbuf[0] = va_arg(va, int))) { p = charbuf; diff --git a/test/libc/stdio/snprintf_test.c b/test/libc/stdio/snprintf_test.c index 21f4f5e06..6f7d895eb 100644 --- a/test/libc/stdio/snprintf_test.c +++ b/test/libc/stdio/snprintf_test.c @@ -71,3 +71,33 @@ TEST(snprintf, testInf) { for (i = 4; i < 10; ++i) ASSERT_EQ(buf[i], '\0'); } + +TEST(snprintf, testUppercaseCConversionSpecifier) { + char buf[10] = {}; + int i = snprintf(buf, sizeof(buf), "%C", L'a'); + + ASSERT_EQ(i, 1); + ASSERT_STREQ(buf, "a"); + + i = snprintf(buf, sizeof(buf), "%C", L'☺'); + ASSERT_EQ(i, 3); + ASSERT_STREQ(buf, "☺"); +} + +// Make sure we don't va_arg the wrong argument size on wide character +// conversion specifiers +TEST(snprintf, + testWideCConversionSpecifierWithLotsOfArgumentsBeforeAndOneAfter) { + char buf[20] = {}; + int i = snprintf(buf, sizeof(buf), "%d%d%d%d%d%d%d%d%lc%d", 0, 0, 0, 0, 0, 0, + 0, 0, L'x', 1); + + ASSERT_EQ(i, 10); + ASSERT_STREQ(buf, "00000000x1"); + + memset(buf, 0, sizeof(buf)); + i = snprintf(buf, sizeof(buf), "%d%d%d%d%d%d%d%d%C%d", 0, 0, 0, 0, 0, 0, 0, 0, + L'x', 1); + ASSERT_EQ(i, 10); + ASSERT_STREQ(buf, "00000000x1"); +}