Fix the printf family for non-ASCII.
The bug here turned out to be that we hadn't increased the constant
corresponding to the maximum number of bytes in a character to match
our new implementation, so any character requiring more than a byte
in UTF-8 would break our printf family.
Bug: 15439554
Change-Id: I693e5e6eb11c640b5886e848502908ec5fff53b1
diff --git a/libc/include/limits.h b/libc/include/limits.h
index dc45902..fb09657 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -112,7 +112,7 @@
#define SSIZE_MAX LONG_MAX
-#define MB_LEN_MAX 6
+#define MB_LEN_MAX 4
/* New code should use sysconf(_SC_PAGE_SIZE) instead. */
#ifndef PAGE_SIZE
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 834dcda..483aaf0 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -167,7 +167,7 @@
extern int wctomb(char *, wchar_t);
extern size_t wcstombs(char *, const wchar_t *, size_t);
-#define MB_CUR_MAX 1
+#define MB_CUR_MAX 4U
#if 0 /* MISSING FROM BIONIC */
extern int on_exit(void (*)(int, void *), void *);
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 0ff85bf..e291f52 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -426,7 +426,26 @@
EXPECT_STREQ("-0.000000", buf);
}
+TEST(stdio, snprintf_utf8_15439554) {
+ // http://b/15439554
+ char buf[BUFSIZ];
+
+ // 1-byte character.
+ snprintf(buf, sizeof(buf), "%dx%d", 1, 2);
+ EXPECT_STREQ("1x2", buf);
+ // 2-byte character.
+ snprintf(buf, sizeof(buf), "%d\xc2\xa2%d", 1, 2);
+ EXPECT_STREQ("1¢2", buf);
+ // 3-byte character.
+ snprintf(buf, sizeof(buf), "%d\xe2\x82\xac%d", 1, 2);
+ EXPECT_STREQ("1€2", buf);
+ // 4-byte character.
+ snprintf(buf, sizeof(buf), "%d\xf0\xa4\xad\xa2%d", 1, 2);
+ EXPECT_STREQ("1𤭢2", buf);
+}
+
TEST(stdio, fprintf_failures_7229520) {
+ // http://b/7229520
FILE* fp;
// Unbuffered case where the fprintf(3) itself fails.
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index e76026f..a5f5f63 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -449,3 +449,32 @@
wmemmove(wstr+5, wstr, sizeof(const_wstr)/sizeof(wchar_t) - 6);
EXPECT_STREQ(L"This This is a test of something or other", wstr);
}
+
+TEST(wchar, mbrtowc_15439554) {
+ // http://b/15439554
+ ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+ uselocale(LC_GLOBAL_LOCALE);
+
+ ASSERT_GE(static_cast<size_t>(MB_LEN_MAX), MB_CUR_MAX);
+ ASSERT_GE(MB_CUR_MAX, 4U);
+
+ wchar_t wc;
+ size_t n;
+
+ // 1-byte character.
+ n = mbrtowc(&wc, "x", MB_CUR_MAX, NULL);
+ EXPECT_EQ(1U, n);
+ EXPECT_EQ(L'x', wc);
+ // 2-byte character.
+ n = mbrtowc(&wc, "\xc2\xa2", MB_CUR_MAX, NULL);
+ EXPECT_EQ(2U, n);
+ EXPECT_EQ(L'¢', wc);
+ // 3-byte character.
+ n = mbrtowc(&wc, "\xe2\x82\xac", MB_CUR_MAX, NULL);
+ EXPECT_EQ(3U, n);
+ EXPECT_EQ(L'€', wc);
+ // 4-byte character.
+ n = mbrtowc(&wc, "\xf0\xa4\xad\xa2", MB_CUR_MAX, NULL);
+ EXPECT_EQ(4U, n);
+ EXPECT_EQ(L'𤭢', wc);
+}