diff options
author | Elliott Hughes <enh@google.com> | 2021-02-18 10:37:22 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2021-02-18 10:37:22 -0800 |
commit | 20c023fdb26fabdec1d49e36eefd62efe9c6ef8b (patch) | |
tree | 40cbf48da639b1586a6bb8bddace0c90189184e2 | |
parent | ef0ec82684ea52ee3a13db8df9103ca314ea17aa (diff) |
iconv(3): ignore src_bytes_left if src_bytes is null.
This is undefined behavior, but glibc and macOS are both lenient, and
someone hit this in the wild, so we may as well be lenient too. (The
only cost is that it's now slightly easier to write code that works on
everything except old versions of Android.)
Bug: https://issuetracker.google.com/180598400
Test: treehugger
Change-Id: Ia217169ea6283cc53f4fbf71e5abfa08356c2049
-rw-r--r-- | libc/bionic/iconv.cpp | 4 | ||||
-rw-r--r-- | tests/iconv_test.cpp | 8 |
2 files changed, 12 insertions, 0 deletions
diff --git a/libc/bionic/iconv.cpp b/libc/bionic/iconv.cpp index 015d70f5e..79a429cb9 100644 --- a/libc/bionic/iconv.cpp +++ b/libc/bionic/iconv.cpp @@ -356,6 +356,10 @@ size_t iconv(iconv_t __converter, errno = EBADF; return -1; } + + // Since none of our encodings are stateful, state flushing is a no-op. + if (!__src_buf) return 0; + return __converter->Convert(__src_buf, __src_bytes_left, __dst_buf, __dst_bytes_left); } diff --git a/tests/iconv_test.cpp b/tests/iconv_test.cpp index 768b4fddd..bd9900039 100644 --- a/tests/iconv_test.cpp +++ b/tests/iconv_test.cpp @@ -451,5 +451,13 @@ TEST(iconv, iconv_initial_shift_state) { EXPECT_EQ(0, errno); EXPECT_EQ(sizeof(out_buf), out_bytes); + // Is a null pointer and so is in_bytes. This isn't specified by POSIX, but + // glibc and macOS both allow that, where Android historically didn't. + // https://issuetracker.google.com/180598400 + errno = 0; + ASSERT_EQ(static_cast<size_t>(0), iconv(c, nullptr, nullptr, &out, &out_bytes)); + EXPECT_EQ(0, errno); + EXPECT_EQ(sizeof(out_buf), out_bytes); + EXPECT_EQ(0, iconv_close(c)); } |