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
diff --git a/libc/Android.mk b/libc/Android.mk
index a06032b..273b73e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -492,7 +492,6 @@
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 e3a40bc..a175d6f 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -93,3 +93,5 @@
#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 646b6b1..b101145 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -451,7 +451,12 @@
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 2e779d8..18fa64a 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -182,6 +183,132 @@
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<void*>(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);