diff --git a/libc/src/__support/wchar/mbrtowc.cpp b/libc/src/__support/wchar/mbrtowc.cpp index 90ba934c42b69..0f730d6e6dbec 100644 --- a/libc/src/__support/wchar/mbrtowc.cpp +++ b/libc/src/__support/wchar/mbrtowc.cpp @@ -37,7 +37,8 @@ ErrorOr mbrtowc(wchar_t *__restrict pwc, const char *__restrict s, } auto wc = char_conv.pop_utf32(); if (wc.has_value()) { - *pwc = wc.value(); + if (pwc != nullptr) + *pwc = wc.value(); // null terminator -> return 0 if (wc.value() == L'\0') return 0; diff --git a/libc/src/wchar/mbtowc.cpp b/libc/src/wchar/mbtowc.cpp index eae39ba6081f3..6d099d43da5fa 100644 --- a/libc/src/wchar/mbtowc.cpp +++ b/libc/src/wchar/mbtowc.cpp @@ -25,10 +25,7 @@ LLVM_LIBC_FUNCTION(int, mbtowc, if (s == nullptr) return 0; internal::mbstate internal_mbstate; - // temp ptr to use if pwc is nullptr - wchar_t buf[1]; - auto ret = - internal::mbrtowc(pwc == nullptr ? buf : pwc, s, n, &internal_mbstate); + auto ret = internal::mbrtowc(pwc, s, n, &internal_mbstate); if (!ret.has_value() || static_cast(ret.value()) == -2) { // Encoding failure libc_errno = EILSEQ; diff --git a/libc/test/src/wchar/mbrtowc_test.cpp b/libc/test/src/wchar/mbrtowc_test.cpp index 5a14d8e25935c..c406300b9ca34 100644 --- a/libc/test/src/wchar/mbrtowc_test.cpp +++ b/libc/test/src/wchar/mbrtowc_test.cpp @@ -190,6 +190,18 @@ TEST_F(LlvmLibcMBRToWCTest, NullString) { ASSERT_ERRNO_SUCCESS(); } +TEST_F(LlvmLibcMBRToWCTest, NullDest) { + const char ch[4] = {static_cast(0xF0), static_cast(0x9F), + static_cast(0xA4), + static_cast(0xA1)}; // 🤡 clown emoji + mbstate_t *mb; + LIBC_NAMESPACE::memset(&mb, 0, sizeof(mbstate_t)); + // reading nullptr should return correct size + size_t n = LIBC_NAMESPACE::mbrtowc(nullptr, ch, 10, mb); + ASSERT_EQ(static_cast(n), 4); + ASSERT_ERRNO_SUCCESS(); +} + TEST_F(LlvmLibcMBRToWCTest, InvalidMBState) { const char ch[4] = {static_cast(0xC2), static_cast(0x8E), static_cast(0xC7), static_cast(0x8C)};