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
This commit is contained in:
Elliott Hughes 2013-09-23 16:02:39 -07:00
parent fc2ceae778
commit 1d13c64d78
4 changed files with 135 additions and 2 deletions

View file

@ -492,7 +492,6 @@ libc_arch_dynamic_src_files := $(_LIBC_ARCH_DYNAMIC_SRC_FILES)
libc_common_cflags := \ libc_common_cflags := \
-DANDROID_CHANGES \ -DANDROID_CHANGES \
-D_LIBC=1 \ -D_LIBC=1 \
-DFLOATING_POINT \
-DINET6 \ -DINET6 \
-I$(LOCAL_PATH)/private \ -I$(LOCAL_PATH)/private \
-DPOSIX_MISTAKE \ -DPOSIX_MISTAKE \

View file

@ -93,3 +93,5 @@ extern int __sdidinit;
#define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0) #define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0)
#define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0) #define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0)
#define FLOATING_POINT

View file

@ -451,7 +451,12 @@ reswitch: switch (ch) {
goto rflag; goto rflag;
#endif #endif
case 'h': case 'h':
flags |= SHORTINT; if (*fmt == 'h') {
fmt++;
flags |= CHARINT;
} else {
flags |= SHORTINT;
}
goto rflag; goto rflag;
case 'j': case 'j':
flags |= MAXINT; flags |= MAXINT;

View file

@ -17,6 +17,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -182,6 +183,132 @@ TEST(stdio, printf_ssize_t) {
snprintf(buf, sizeof(buf), "%zd", v); 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) { TEST(stdio, popen) {
FILE* fp = popen("cat /proc/version", "r"); FILE* fp = popen("cat /proc/version", "r");
ASSERT_TRUE(fp != NULL); ASSERT_TRUE(fp != NULL);