From 4e5860958767ecc7bc455d2a5e1d2a2096a1c79f Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Sun, 20 Jul 2014 11:51:26 -0700 Subject: [PATCH] Fix mbsrtowcs(3)'s handling of len parameter. The len parameter is a _maximum_ length. The previous code was treating it as an exact length, causing the following typical call to fail: mbsrtowcs(out, &in, sizeof(out), state); // sizeof(out) > strlen(in) Change-Id: I48e474fd54ea5f122bc168a4d74bfe08704f28cc (cherry picked from commit 6b55ba54eff4657cffe053b71e1c9cce2944a8a9) --- libc/bionic/wchar.cpp | 7 +++---- tests/wchar_test.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libc/bionic/wchar.cpp b/libc/bionic/wchar.cpp index ecb8b3391..438ce0379 100644 --- a/libc/bionic/wchar.cpp +++ b/libc/bionic/wchar.cpp @@ -116,11 +116,10 @@ size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstat if (static_cast((*src)[i]) < 0x80) { // Fast path for plain ASCII characters. dst[o] = (*src)[i]; - if ((*src)[i] == '\0') { - *src = NULL; - return reset_and_return_illegal(EILSEQ, state); - } r = 1; + if ((*src)[i] == '\0') { + break; + } } else { r = mbrtowc(dst + o, *src + i, nmc - i, state); if (r == __MB_ERR_ILLEGAL_SEQUENCE) { diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp index a5f5f63a2..f052ce6f1 100644 --- a/tests/wchar_test.cpp +++ b/tests/wchar_test.cpp @@ -340,8 +340,19 @@ void test_mbsrtowcs(mbstate_t* ps) { ASSERT_EQ(static_cast(0x00a2), out[1]); ASSERT_EQ(static_cast(0x20ac), out[2]); ASSERT_EQ(static_cast(0x24b62), out[3]); + // Check that valid has advanced to the next unread character. ASSERT_EQ('e', *valid); + wmemset(out, L'x', sizeof(out) / sizeof(wchar_t)); + ASSERT_EQ(2U, mbsrtowcs(out, &valid, 4, ps)); + ASSERT_EQ(L'e', out[0]); + ASSERT_EQ(L'f', out[1]); + ASSERT_EQ(L'\0', out[2]); + // Check that we didn't clobber the rest of out. + ASSERT_EQ(L'x', out[3]); + // Check that valid has advanced to the end of the string. + ASSERT_EQ(L'\0', *valid); + const char* invalid = "A" "\xc2\x20" "ef"; ASSERT_EQ(static_cast(-1), mbsrtowcs(out, &invalid, 4, ps)); EXPECT_EQ(EILSEQ, errno);