From 1d13c64d781a87dfa3f01e5c179bfa36748786af Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 23 Sep 2013 16:02:39 -0700 Subject: [PATCH] Fix %hhd formats in the printf family. Found by adapting the simple unit tests for libc logging to test snprintf too. Fix taken from upstream OpenBSD without updating the rest of stdio. Change-Id: Ie339a8e9393a36080147aae4d6665118e5d93647 --- libc/Android.mk | 1 - libc/stdio/local.h | 2 + libc/stdio/vfprintf.c | 7 ++- tests/stdio_test.cpp | 127 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 2 deletions(-) diff --git a/libc/Android.mk b/libc/Android.mk index a06032bd9..273b73e3d 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -492,7 +492,6 @@ libc_arch_dynamic_src_files := $(_LIBC_ARCH_DYNAMIC_SRC_FILES) libc_common_cflags := \ -DANDROID_CHANGES \ -D_LIBC=1 \ - -DFLOATING_POINT \ -DINET6 \ -I$(LOCAL_PATH)/private \ -DPOSIX_MISTAKE \ diff --git a/libc/stdio/local.h b/libc/stdio/local.h index e3a40bca3..a175d6fa0 100644 --- a/libc/stdio/local.h +++ b/libc/stdio/local.h @@ -93,3 +93,5 @@ extern int __sdidinit; #define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0) #define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0) + +#define FLOATING_POINT diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c index 646b6b11a..b1011456a 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.c @@ -451,7 +451,12 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': - flags |= SHORTINT; + if (*fmt == 'h') { + fmt++; + flags |= CHARINT; + } else { + flags |= SHORTINT; + } goto rflag; case 'j': flags |= MAXINT; diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 2e779d81c..18fa64a7c 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -182,6 +183,132 @@ TEST(stdio, printf_ssize_t) { snprintf(buf, sizeof(buf), "%zd", v); } +TEST(stdio, snprintf_smoke) { + char buf[BUFSIZ]; + + snprintf(buf, sizeof(buf), "a"); + EXPECT_STREQ("a", buf); + + snprintf(buf, sizeof(buf), "%%"); + EXPECT_STREQ("%", buf); + + snprintf(buf, sizeof(buf), "01234"); + EXPECT_STREQ("01234", buf); + + snprintf(buf, sizeof(buf), "a%sb", "01234"); + EXPECT_STREQ("a01234b", buf); + + char* s = NULL; + snprintf(buf, sizeof(buf), "a%sb", s); + EXPECT_STREQ("a(null)b", buf); + + snprintf(buf, sizeof(buf), "aa%scc", "bb"); + EXPECT_STREQ("aabbcc", buf); + + snprintf(buf, sizeof(buf), "a%cc", 'b'); + EXPECT_STREQ("abc", buf); + + snprintf(buf, sizeof(buf), "a%db", 1234); + EXPECT_STREQ("a1234b", buf); + + snprintf(buf, sizeof(buf), "a%db", -8123); + EXPECT_STREQ("a-8123b", buf); + + snprintf(buf, sizeof(buf), "a%hdb", 0x7fff0010); + EXPECT_STREQ("a16b", buf); + + snprintf(buf, sizeof(buf), "a%hhdb", 0x7fffff10); + EXPECT_STREQ("a16b", buf); + + snprintf(buf, sizeof(buf), "a%lldb", 0x1000000000LL); + EXPECT_STREQ("a68719476736b", buf); + + snprintf(buf, sizeof(buf), "a%ldb", 70000L); + EXPECT_STREQ("a70000b", buf); + + snprintf(buf, sizeof(buf), "a%pb", reinterpret_cast(0xb0001234)); + EXPECT_STREQ("a0xb0001234b", buf); + + snprintf(buf, sizeof(buf), "a%xz", 0x12ab); + EXPECT_STREQ("a12abz", buf); + + snprintf(buf, sizeof(buf), "a%Xz", 0x12ab); + EXPECT_STREQ("a12ABz", buf); + + snprintf(buf, sizeof(buf), "a%08xz", 0x123456); + EXPECT_STREQ("a00123456z", buf); + + snprintf(buf, sizeof(buf), "a%5dz", 1234); + EXPECT_STREQ("a 1234z", buf); + + snprintf(buf, sizeof(buf), "a%05dz", 1234); + EXPECT_STREQ("a01234z", buf); + + snprintf(buf, sizeof(buf), "a%8dz", 1234); + EXPECT_STREQ("a 1234z", buf); + + snprintf(buf, sizeof(buf), "a%-8dz", 1234); + EXPECT_STREQ("a1234 z", buf); + + snprintf(buf, sizeof(buf), "A%-11sZ", "abcdef"); + EXPECT_STREQ("Aabcdef Z", buf); + + snprintf(buf, sizeof(buf), "A%s:%dZ", "hello", 1234); + EXPECT_STREQ("Ahello:1234Z", buf); + + snprintf(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5); + EXPECT_STREQ("a005:5:05z", buf); + + void* p = NULL; + snprintf(buf, sizeof(buf), "a%d,%pz", 5, p); + EXPECT_STREQ("a5,0x0z", buf); + + snprintf(buf, sizeof(buf), "a%lld,%d,%d,%dz", 0x1000000000LL, 6, 7, 8); + EXPECT_STREQ("a68719476736,6,7,8z", buf); + + snprintf(buf, sizeof(buf), "a_%f_b", 1.23f); + EXPECT_STREQ("a_1.230000_b", buf); + + snprintf(buf, sizeof(buf), "a_%g_b", 3.14d); + EXPECT_STREQ("a_3.14_b", buf); +} + +TEST(stdio, snprintf_d_INT_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%d", INT_MAX); + EXPECT_STREQ("2147483647", buf); +} + +TEST(stdio, snprintf_d_INT_MIN) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%d", INT_MIN); + EXPECT_STREQ("-2147483648", buf); +} + +TEST(stdio, snprintf_ld_LONG_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%ld", LONG_MAX); + EXPECT_STREQ("2147483647", buf); +} + +TEST(stdio, snprintf_ld_LONG_MIN) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%ld", LONG_MIN); + EXPECT_STREQ("-2147483648", buf); +} + +TEST(stdio, snprintf_lld_LLONG_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%lld", LLONG_MAX); + EXPECT_STREQ("9223372036854775807", buf); +} + +TEST(stdio, snprintf_lld_LLONG_MIN) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%lld", LLONG_MIN); + EXPECT_STREQ("-9223372036854775808", buf); +} + TEST(stdio, popen) { FILE* fp = popen("cat /proc/version", "r"); ASSERT_TRUE(fp != NULL);