1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

CharPointer: Fix a crash in the UTF32 unit tests

In a recent version of Xcode (26.1) release builds would crash the
unittest runner during any tests using a std::vector<char32_t> where
its data was reinterpreted as const CharPointer_UTF32::CharType*.
Similar attempts were made to update the UTF8 a UTF16 tests,
unfortunately avoiding a reinterpret_cast for UTF16 isn't as easy
because CharPointer_UTF16 uses a signed integer type which makes the
test data more awkward to work with.
This commit is contained in:
Anthony Nicholls 2025-11-20 16:21:54 +00:00 committed by Anthony Nicholls
parent c37c18c5b4
commit a4e03bdad1
2 changed files with 25 additions and 26 deletions

View file

@ -42,10 +42,7 @@ public:
void runTest() final
{
const auto toCharType = [] (const std::vector<char32_t>& str)
{
return reinterpret_cast<const CharPointer_UTF32::CharType*> (str.data());
};
using Utf32Vector = std::vector<CharPointer_UTF32::CharType>;
const auto getNumBytes = [] (const auto& str)
{
@ -54,50 +51,50 @@ public:
beginTest ("String validation - empty string / null-terminator");
{
const std::vector<CharPointer_UTF32::CharType> string { 0x0 };
const Utf32Vector string { 0x0 };
expect (CharPointer_UTF32::isValidString (string.data(), getNumBytes (string)));
}
beginTest ("String validation - ascii");
{
const std::vector<char32_t> string { 0x54, 0x65, 0x73, 0x74, 0x21, 0x0 }; // Test!
expect (CharPointer_UTF32::isValidString (toCharType (string), getNumBytes (string)));
const Utf32Vector string { 0x54, 0x65, 0x73, 0x74, 0x21, 0x0 }; // Test!
expect (CharPointer_UTF32::isValidString (string.data(), getNumBytes (string)));
}
beginTest ("String validation - 2-byte code points");
{
const std::vector<char32_t> string { 0x54, 0x65, 0x73, 0x74, 0x20ac, 0x0 }; // Test€
expect (CharPointer_UTF32::isValidString (toCharType (string), getNumBytes (string)));
const Utf32Vector string { 0x54, 0x65, 0x73, 0x74, 0x20ac, 0x0 }; // Test€
expect (CharPointer_UTF32::isValidString (string.data(), getNumBytes (string)));
}
beginTest ("String validation - maximum code point");
{
const std::vector<char32_t> string1 { 0x54, 0x65, 0x73, 0x74, 0x10ffff, 0x0 };
expect (CharPointer_UTF32::isValidString (toCharType (string1), getNumBytes (string1)));
const Utf32Vector string1 { 0x54, 0x65, 0x73, 0x74, 0x10ffff, 0x0 };
expect (CharPointer_UTF32::isValidString (string1.data(), getNumBytes (string1)));
const std::vector<char32_t> string2 { 0x54, 0x65, 0x73, 0x74, 0x110000, 0x0 };
expect (! CharPointer_UTF32::isValidString (toCharType (string2), getNumBytes (string2)));
const Utf32Vector string2 { 0x54, 0x65, 0x73, 0x74, 0x110000, 0x0 };
expect (! CharPointer_UTF32::isValidString (string2.data(), getNumBytes (string2)));
}
beginTest ("String validation - characters after a null terminator are ignored");
{
const std::vector<char32_t> string { 0x54, 0x65, 0x73, 0x74, 0x0, 0x110000 };
expect (CharPointer_UTF32::isValidString (toCharType (string), getNumBytes (string)));
const Utf32Vector string { 0x54, 0x65, 0x73, 0x74, 0x0, 0x110000 };
expect (CharPointer_UTF32::isValidString (string.data(), getNumBytes (string)));
}
beginTest ("String validation - characters exceeding max bytes are ignored");
{
const std::vector<char32_t> string { 0x54, 0x65, 0x73, 0x74, 0x110000 };
expect (CharPointer_UTF32::isValidString (toCharType (string), 8));
const Utf32Vector string { 0x54, 0x65, 0x73, 0x74, 0x110000 };
expect (CharPointer_UTF32::isValidString (string.data(), 8));
}
beginTest ("String validation - surrogate code points are invalid");
{
const std::vector<char32_t> highSurrogate { 0xd800 };
expect (! CharPointer_UTF32::isValidString (toCharType (highSurrogate), getNumBytes (highSurrogate)));
const Utf32Vector highSurrogate { 0xd800 };
expect (! CharPointer_UTF32::isValidString (highSurrogate.data(), getNumBytes (highSurrogate)));
const std::vector<char32_t> lowSurrogate { 0xdfff };
expect (! CharPointer_UTF32::isValidString (toCharType (lowSurrogate), getNumBytes (lowSurrogate)));
const Utf32Vector lowSurrogate { 0xdfff };
expect (! CharPointer_UTF32::isValidString (lowSurrogate.data(), getNumBytes (lowSurrogate)));
}
}
};

View file

@ -42,15 +42,17 @@ public:
void runTest() final
{
using Utf8Vector = std::vector<CharPointer_UTF8::CharType>;
beginTest ("String validation - empty string / null-terminator");
{
const std::vector<CharPointer_UTF8::CharType> string { '\0' };
const Utf8Vector string { '\0' };
expect (CharPointer_UTF8::isValidString (string.data(), (int) string.size()));
}
beginTest ("String validation - ascii");
{
const std::vector<CharPointer_UTF8::CharType> string { 'T', 'e', 's', 'T', '!', '\0' }; // Test!
const Utf8Vector string { 'T', 'e', 's', 'T', '!', '\0' }; // Test!
expect (CharPointer_UTF8::isValidString (string.data(), (int) string.size()));
}
@ -58,19 +60,19 @@ public:
beginTest ("String validation - continuation characters are invalid when not proceeded by the correct bytes");
{
const std::vector<CharPointer_UTF8::CharType> string { continuationCharacter };
const Utf8Vector string { continuationCharacter };
expect (! CharPointer_UTF8::isValidString (string.data(), (int) string.size()));
}
beginTest ("String validation - characters after a null terminator are ignored");
{
const std::vector<CharPointer_UTF8::CharType> string { 'T', 'e', 's', 'T', '\0', continuationCharacter };
const Utf8Vector string { 'T', 'e', 's', 'T', '\0', continuationCharacter };
expect (CharPointer_UTF8::isValidString (string.data(), (int) string.size()));
}
beginTest ("String validation - characters exceeding max bytes are ignored");
{
const std::vector<CharPointer_UTF8::CharType> string { 'T', 'e', 's', 'T', continuationCharacter };
const Utf8Vector string { 'T', 'e', 's', 'T', continuationCharacter };
expect (CharPointer_UTF8::isValidString (string.data(), 4));
}