summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2021-02-18 10:37:22 -0800
committerElliott Hughes <enh@google.com>2021-02-18 10:37:22 -0800
commit20c023fdb26fabdec1d49e36eefd62efe9c6ef8b (patch)
tree40cbf48da639b1586a6bb8bddace0c90189184e2
parentef0ec82684ea52ee3a13db8df9103ca314ea17aa (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.cpp4
-rw-r--r--tests/iconv_test.cpp8
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));
}