From acb469ae2e18bf35a56f534e53a680890948bfbd Mon Sep 17 00:00:00 2001 From: Vasili Galka Date: Mon, 12 Mar 2018 14:43:29 +0200 Subject: [PATCH] Fixed UTF8/16 converters to support empty string input Previously an exception was thrown since Win32 WideCharToMultiByte API returns error on zero-length input. --- include/fmt/format.cc | 14 ++++++++++++++ test/util-test.cc | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/fmt/format.cc b/include/fmt/format.cc index 429657fb..0b4f2d80 100644 --- a/include/fmt/format.cc +++ b/include/fmt/format.cc @@ -283,6 +283,13 @@ FMT_FUNC internal::utf8_to_utf16::utf8_to_utf16(string_view s) { if (s.size() > INT_MAX) FMT_THROW(windows_error(ERROR_INVALID_PARAMETER, ERROR_MSG)); int s_size = static_cast(s.size()); + if (s_size == 0) { + // MultiByteToWideChar does not support zero length, handle separately. + buffer_.resize(1); + buffer_[0] = 0; + return; + } + int length = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0); if (length == 0) @@ -306,6 +313,13 @@ FMT_FUNC int internal::utf16_to_utf8::convert(wstring_view s) { if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER; int s_size = static_cast(s.size()); + if (s_size == 0) { + // WideCharToMultiByte does not support zero length, handle separately. + buffer_.resize(1); + buffer_[0] = 0; + return 0; + } + int length = WideCharToMultiByte( CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL); if (length == 0) diff --git a/test/util-test.cc b/test/util-test.cc index 97dabfbb..11957655 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -665,6 +665,13 @@ TEST(UtilTest, UTF16ToUTF8) { EXPECT_EQ(s.size(), u.size()); } +TEST(UtilTest, UTF16ToUTF8EmptyString) { + std::string s = ""; + fmt::internal::utf16_to_utf8 u(L""); + EXPECT_EQ(s, u.str()); + EXPECT_EQ(s.size(), u.size()); +} + TEST(UtilTest, UTF8ToUTF16) { std::string s = "лошадка"; fmt::internal::utf8_to_utf16 u(s.c_str()); @@ -672,6 +679,13 @@ TEST(UtilTest, UTF8ToUTF16) { EXPECT_EQ(7, u.size()); } +TEST(UtilTest, UTF8ToUTF16EmptyString) { + std::string s = ""; + fmt::internal::utf8_to_utf16 u(s.c_str()); + EXPECT_EQ(L"", u.str()); + EXPECT_EQ(s.size(), u.size()); +} + template void check_utf_conversion_error( const char *message,