diff --git a/stl/src/format.cpp b/stl/src/format.cpp index 67a91356a9d..24033999edb 100644 --- a/stl/src/format.cpp +++ b/stl/src/format.cpp @@ -31,8 +31,15 @@ extern "C" [[nodiscard]] __std_win_error __stdcall __std_get_cvt( break; } - for (unsigned char _First = _Info.LeadByte[_Idx], _Last = _Info.LeadByte[_Idx + 1]; _First != _Last; ++_First) { - _Pcvt->_Isleadbyte[_First >> 3] |= 1u << (_First & 0b111u); + const unsigned int _First = _Info.LeadByte[_Idx]; + const unsigned int _Last = _Info.LeadByte[_Idx + 1]; + + if (_Last < _First) { + continue; + } + + for (unsigned int _Byte = _First; _Byte <= _Last; ++_Byte) { + _Pcvt->_Isleadbyte[_Byte >> 3] |= 1u << (_Byte & 0b111u); } } diff --git a/tests/tr1/tests/cwchar2/test.cpp b/tests/tr1/tests/cwchar2/test.cpp index a8d8e43d749..5bfb4e72860 100644 --- a/tests/tr1/tests/cwchar2/test.cpp +++ b/tests/tr1/tests/cwchar2/test.cpp @@ -5,7 +5,9 @@ #define TEST_NAME ", part 2" #include "tdefs.h" +#include #include +#include #include #include @@ -50,6 +52,27 @@ void test_cpp() { // test C++ header CHECK_INT(STDx mbrtowc(&wc, abc + 3, 9, &mbst), 0); CHECK_INT(wc, L'\0'); + { // UTF-8 overlong sequences should be rejected + const char overlong_nul[] = "\xC0\x80"; + const char overlong_A[] = "\xC1\x81"; + + if (std::setlocale(LC_CTYPE, ".UTF-8") != nullptr) { + STDx mbstate_t utf8_state{}; + wchar_t wide_out; + + errno = 0; + CHECK_INT(STDx mbrtowc(&wide_out, overlong_nul, sizeof(overlong_nul) - 1, &utf8_state), -1); + CHECK_INT(errno, EILSEQ); + + utf8_state = STDx mbstate_t{}; + errno = 0; + CHECK_INT(STDx mbrtowc(&wide_out, overlong_A, sizeof(overlong_A) - 1, &utf8_state), -1); + CHECK_INT(errno, EILSEQ); + + std::setlocale(LC_CTYPE, "C"); + } + } + CHECK(STDx mbsinit(&mbst) != 0); pc = &abc[0]; CHECK_INT(STDx mbsrtowcs(wcs, &pc, 10, &mbst), 3);