Bug Summary

File:root/firefox-clang/mfbt/tests/TestUtf8.cpp
Warning:line 179, column 9
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name TestUtf8.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/mfbt/tests -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/mfbt/tests -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -I /root/firefox-clang/mfbt/tests -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/mfbt/tests -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/testing -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/mfbt/tests/TestUtf8.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#define MOZ_PRETEND_NO_JSRUST1 1
6
7#include "mozilla/Assertions.h"
8#include "mozilla/EnumSet.h"
9#include "mozilla/IntegerRange.h"
10#include "mozilla/Span.h"
11#include "mozilla/Utf8.h"
12
13using mozilla::AsChars;
14using mozilla::DecodeOneUtf8CodePoint;
15using mozilla::EnumSet;
16using mozilla::IntegerRange;
17using mozilla::IsAscii;
18using mozilla::IsUtf8;
19using mozilla::Span;
20using mozilla::Utf8Unit;
21
22static void TestUtf8Unit() {
23 Utf8Unit c('A');
24 MOZ_RELEASE_ASSERT(c.toChar() == 'A')do { static_assert( mozilla::detail::AssertionConditionType<
decltype(c.toChar() == 'A')>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(c.toChar() == 'A'))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("c.toChar() == 'A'"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 24); do { } while
(false); do { MOZ_CrashSequence(__null, 24); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
25 MOZ_RELEASE_ASSERT(c == Utf8Unit('A'))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(c == Utf8Unit('A'))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(c == Utf8Unit('A')))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("c == Utf8Unit('A')"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 25); do { } while
(false); do { MOZ_CrashSequence(__null, 25); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
26 MOZ_RELEASE_ASSERT(c != Utf8Unit('B'))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(c != Utf8Unit('B'))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(c != Utf8Unit('B')))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("c != Utf8Unit('B')"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 26); do { } while
(false); do { MOZ_CrashSequence(__null, 26); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
27 MOZ_RELEASE_ASSERT(c.toUint8() == 0x41)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(c.toUint8() == 0x41)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(c.toUint8() == 0x41))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("c.toUint8() == 0x41"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 27); do { } while
(false); do { MOZ_CrashSequence(__null, 27); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
28
29 unsigned char asUnsigned = 'A';
30 MOZ_RELEASE_ASSERT(c.toUnsignedChar() == asUnsigned)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(c.toUnsignedChar() == asUnsigned)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(c.toUnsignedChar() == asUnsigned
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"c.toUnsignedChar() == asUnsigned", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 30); do { } while (false); do { MOZ_CrashSequence(__null, 30
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
31 MOZ_RELEASE_ASSERT(Utf8Unit('B').toUnsignedChar() != asUnsigned)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Utf8Unit('B').toUnsignedChar() != asUnsigned)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(Utf8Unit('B').toUnsignedChar() != asUnsigned))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("Utf8Unit('B').toUnsignedChar() != asUnsigned"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 31); do { } while
(false); do { MOZ_CrashSequence(__null, 31); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
32
33 Utf8Unit first('@');
34 Utf8Unit second('#');
35
36 MOZ_RELEASE_ASSERT(first != second)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(first != second)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(first != second))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("first != second"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 36); do { } while
(false); do { MOZ_CrashSequence(__null, 36); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
37
38 first = second;
39 MOZ_RELEASE_ASSERT(first == second)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(first == second)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(first == second))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("first == second"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 39); do { } while
(false); do { MOZ_CrashSequence(__null, 39); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
40}
41
42template <typename Char>
43struct ToUtf8Units {
44 public:
45 explicit ToUtf8Units(const Char* aStart, const Char* aEnd)
46 : lead(Utf8Unit(aStart[0])), iter(aStart + 1), end(aEnd) {
47 MOZ_RELEASE_ASSERT(!IsAscii(aStart[0]))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsAscii(aStart[0]))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsAscii(aStart[0])))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!IsAscii(aStart[0])"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 47); do { } while
(false); do { MOZ_CrashSequence(__null, 47); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
48 }
49
50 const Utf8Unit lead;
51 const Char* iter;
52 const Char* const end;
53};
54
55class AssertIfCalled {
56 public:
57 template <typename... Args>
58 void operator()(Args&&... aArgs) {
59 MOZ_RELEASE_ASSERT(false, "AssertIfCalled instance was called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "AssertIfCalled instance was called"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 59); do {
} while (false); do { MOZ_CrashSequence(__null, 59); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
60 }
61};
62
63// NOTE: For simplicity in treating |aCharN| identically regardless whether it's
64// a string literal or a more-generalized array, we require |aCharN| be
65// null-terminated.
66
67template <typename Char, size_t N>
68static void ExpectValidCodePoint(const Char (&aCharN)[N],
69 char32_t aExpectedCodePoint) {
70 MOZ_RELEASE_ASSERT(aCharN[N - 1] == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 73); do {
} while (false); do { MOZ_CrashSequence(__null, 73); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
71 "array must be null-terminated for |aCharN + N - 1| to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 73); do {
} while (false); do { MOZ_CrashSequence(__null, 73); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
72 "compute the value of |aIter| as altered by "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 73); do {
} while (false); do { MOZ_CrashSequence(__null, 73); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
73 "DecodeOneUtf8CodePoint")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 73); do {
} while (false); do { MOZ_CrashSequence(__null, 73); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
74
75 ToUtf8Units<Char> simpleUnit(aCharN, aCharN + N - 1);
76 auto simple =
77 DecodeOneUtf8CodePoint(simpleUnit.lead, &simpleUnit.iter, simpleUnit.end);
78 MOZ_RELEASE_ASSERT(simple.isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(simple.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(simple.isSome()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("simple.isSome()"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 78); do { } while
(false); do { MOZ_CrashSequence(__null, 78); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
79 MOZ_RELEASE_ASSERT(*simple == aExpectedCodePoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*simple == aExpectedCodePoint)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*simple == aExpectedCodePoint
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"*simple == aExpectedCodePoint", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 79); do { } while (false); do { MOZ_CrashSequence(__null, 79
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
80 MOZ_RELEASE_ASSERT(simpleUnit.iter == simpleUnit.end)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(simpleUnit.iter == simpleUnit.end)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(simpleUnit.iter == simpleUnit
.end))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("simpleUnit.iter == simpleUnit.end", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 80); do { } while (false); do { MOZ_CrashSequence(__null, 80
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
81
82 ToUtf8Units<Char> complexUnit(aCharN, aCharN + N - 1);
83 auto complex = DecodeOneUtf8CodePoint(
84 complexUnit.lead, &complexUnit.iter, complexUnit.end, AssertIfCalled(),
85 AssertIfCalled(), AssertIfCalled(), AssertIfCalled(), AssertIfCalled());
86 MOZ_RELEASE_ASSERT(complex.isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(complex.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(complex.isSome()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("complex.isSome()"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 86); do { } while
(false); do { MOZ_CrashSequence(__null, 86); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
87 MOZ_RELEASE_ASSERT(*complex == aExpectedCodePoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*complex == aExpectedCodePoint)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*complex == aExpectedCodePoint
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"*complex == aExpectedCodePoint", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 87); do { } while (false); do { MOZ_CrashSequence(__null, 87
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
88 MOZ_RELEASE_ASSERT(complexUnit.iter == complexUnit.end)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(complexUnit.iter == complexUnit.end)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(complexUnit.iter == complexUnit
.end))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("complexUnit.iter == complexUnit.end", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 88); do { } while (false); do { MOZ_CrashSequence(__null, 88
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
89}
90
91enum class InvalidUtf8Reason {
92 BadLeadUnit,
93 NotEnoughUnits,
94 BadTrailingUnit,
95 BadCodePoint,
96 NotShortestForm,
97};
98
99template <typename Char, size_t N>
100static void ExpectInvalidCodePointHelper(const Char (&aCharN)[N],
101 InvalidUtf8Reason aExpectedReason,
102 uint8_t aExpectedUnitsAvailable,
103 uint8_t aExpectedUnitsNeeded,
104 char32_t aExpectedBadCodePoint,
105 uint8_t aExpectedUnitsObserved) {
106 MOZ_RELEASE_ASSERT(aCharN[N - 1] == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 109); do
{ } while (false); do { MOZ_CrashSequence(__null, 109); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
1
Assuming the condition is true
2
Taking false branch
3
Loop condition is false. Exiting loop
107 "array must be null-terminated for |aCharN + N - 1| to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 109); do
{ } while (false); do { MOZ_CrashSequence(__null, 109); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
108 "compute the value of |aIter| as altered by "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 109); do
{ } while (false); do { MOZ_CrashSequence(__null, 109); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
109 "DecodeOneUtf8CodePoint")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCharN[N - 1] == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCharN[N - 1] == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aCharN[N - 1] == 0"
" (" "array must be null-terminated for |aCharN + N - 1| to "
"compute the value of |aIter| as altered by " "DecodeOneUtf8CodePoint"
")", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 109); do
{ } while (false); do { MOZ_CrashSequence(__null, 109); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
110
111 ToUtf8Units<Char> simpleUnit(aCharN, aCharN + N - 1);
112 auto simple =
113 DecodeOneUtf8CodePoint(simpleUnit.lead, &simpleUnit.iter, simpleUnit.end);
114 MOZ_RELEASE_ASSERT(simple.isNothing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(simple.isNothing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(simple.isNothing()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("simple.isNothing()"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 114); do { }
while (false); do { MOZ_CrashSequence(__null, 114); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
4
Assuming the condition is false
5
Taking false branch
6
Loop condition is false. Exiting loop
115 MOZ_RELEASE_ASSERT(static_cast<const void*>(simpleUnit.iter) == aCharN)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(static_cast<const void*>(simpleUnit.iter) == aCharN
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(static_cast<const void*>(simpleUnit.iter) == aCharN
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"static_cast<const void*>(simpleUnit.iter) == aCharN", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 115); do { } while (false); do { MOZ_CrashSequence(__null, 115
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
7
Taking false branch
8
Loop condition is false. Exiting loop
116
117 EnumSet<InvalidUtf8Reason> reasons;
118 uint8_t unitsAvailable;
119 uint8_t unitsNeeded;
120 char32_t badCodePoint;
121 uint8_t unitsObserved;
9
'unitsObserved' declared without an initial value
122
123 struct OnNotShortestForm {
124 EnumSet<InvalidUtf8Reason>& reasons;
125 char32_t& badCodePoint;
126 uint8_t& unitsObserved;
127
128 void operator()(char32_t aBadCodePoint, uint8_t aUnitsObserved) {
129 reasons += InvalidUtf8Reason::NotShortestForm;
130 badCodePoint = aBadCodePoint;
131 unitsObserved = aUnitsObserved;
132 }
133 };
134
135 ToUtf8Units<Char> complexUnit(aCharN, aCharN + N - 1);
136 auto complex = DecodeOneUtf8CodePoint(
137 complexUnit.lead, &complexUnit.iter, complexUnit.end,
138 [&reasons]() { reasons += InvalidUtf8Reason::BadLeadUnit; },
139 [&reasons, &unitsAvailable, &unitsNeeded](uint8_t aUnitsAvailable,
140 uint8_t aUnitsNeeded) {
141 reasons += InvalidUtf8Reason::NotEnoughUnits;
142 unitsAvailable = aUnitsAvailable;
143 unitsNeeded = aUnitsNeeded;
144 },
145 [&reasons, &unitsObserved](uint8_t aUnitsObserved) {
146 reasons += InvalidUtf8Reason::BadTrailingUnit;
147 unitsObserved = aUnitsObserved;
148 },
149 [&reasons, &badCodePoint, &unitsObserved](char32_t aBadCodePoint,
150 uint8_t aUnitsObserved) {
151 reasons += InvalidUtf8Reason::BadCodePoint;
152 badCodePoint = aBadCodePoint;
153 unitsObserved = aUnitsObserved;
154 },
155 [&reasons, &badCodePoint, &unitsObserved](char32_t aBadCodePoint,
156 uint8_t aUnitsObserved) {
157 reasons += InvalidUtf8Reason::NotShortestForm;
158 badCodePoint = aBadCodePoint;
159 unitsObserved = aUnitsObserved;
160 });
161 MOZ_RELEASE_ASSERT(complex.isNothing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(complex.isNothing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(complex.isNothing()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("complex.isNothing()"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 161); do { }
while (false); do { MOZ_CrashSequence(__null, 161); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10
Assuming the condition is false
11
Taking false branch
12
Loop condition is false. Exiting loop
162 MOZ_RELEASE_ASSERT(static_cast<const void*>(complexUnit.iter) == aCharN)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(static_cast<const void*>(complexUnit.iter) == aCharN
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(static_cast<const void*>(complexUnit.iter) == aCharN
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"static_cast<const void*>(complexUnit.iter) == aCharN",
"/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 162); do { } while
(false); do { MOZ_CrashSequence(__null, 162); __attribute__(
(nomerge)) ::abort(); } while (false); } } while (false)
;
13
Taking false branch
14
Loop condition is false. Exiting loop
163
164 bool alreadyIterated = false;
165 for (InvalidUtf8Reason reason : reasons) {
166 MOZ_RELEASE_ASSERT(!alreadyIterated)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!alreadyIterated)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!alreadyIterated))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!alreadyIterated"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 166); do { }
while (false); do { MOZ_CrashSequence(__null, 166); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
15
Taking false branch
16
Loop condition is false. Exiting loop
167 alreadyIterated = true;
168
169 switch (reason) {
17
Control jumps to 'case BadTrailingUnit:' at line 178
170 case InvalidUtf8Reason::BadLeadUnit:
171 break;
172
173 case InvalidUtf8Reason::NotEnoughUnits:
174 MOZ_RELEASE_ASSERT(unitsAvailable == aExpectedUnitsAvailable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unitsAvailable == aExpectedUnitsAvailable)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(unitsAvailable == aExpectedUnitsAvailable))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("unitsAvailable == aExpectedUnitsAvailable"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 174); do { }
while (false); do { MOZ_CrashSequence(__null, 174); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
175 MOZ_RELEASE_ASSERT(unitsNeeded == aExpectedUnitsNeeded)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unitsNeeded == aExpectedUnitsNeeded)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(unitsNeeded == aExpectedUnitsNeeded
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"unitsNeeded == aExpectedUnitsNeeded", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 175); do { } while (false); do { MOZ_CrashSequence(__null, 175
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
176 break;
177
178 case InvalidUtf8Reason::BadTrailingUnit:
179 MOZ_RELEASE_ASSERT(unitsObserved == aExpectedUnitsObserved)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unitsObserved == aExpectedUnitsObserved)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(unitsObserved == aExpectedUnitsObserved))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("unitsObserved == aExpectedUnitsObserved"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 179); do { }
while (false); do { MOZ_CrashSequence(__null, 179); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
18
The left operand of '==' is a garbage value
180 break;
181
182 case InvalidUtf8Reason::BadCodePoint:
183 MOZ_RELEASE_ASSERT(badCodePoint == aExpectedBadCodePoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(badCodePoint == aExpectedBadCodePoint)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(badCodePoint == aExpectedBadCodePoint))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("badCodePoint == aExpectedBadCodePoint"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 183); do { }
while (false); do { MOZ_CrashSequence(__null, 183); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
184 MOZ_RELEASE_ASSERT(unitsObserved == aExpectedUnitsObserved)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unitsObserved == aExpectedUnitsObserved)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(unitsObserved == aExpectedUnitsObserved))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("unitsObserved == aExpectedUnitsObserved"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 184); do { }
while (false); do { MOZ_CrashSequence(__null, 184); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
185 break;
186
187 case InvalidUtf8Reason::NotShortestForm:
188 MOZ_RELEASE_ASSERT(badCodePoint == aExpectedBadCodePoint)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(badCodePoint == aExpectedBadCodePoint)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(badCodePoint == aExpectedBadCodePoint))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("badCodePoint == aExpectedBadCodePoint"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 188); do { }
while (false); do { MOZ_CrashSequence(__null, 188); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
189 MOZ_RELEASE_ASSERT(unitsObserved == aExpectedUnitsObserved)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unitsObserved == aExpectedUnitsObserved)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(unitsObserved == aExpectedUnitsObserved))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("unitsObserved == aExpectedUnitsObserved"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 189); do { }
while (false); do { MOZ_CrashSequence(__null, 189); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
190 break;
191 }
192 }
193}
194
195// NOTE: For simplicity in treating |aCharN| identically regardless whether it's
196// a string literal or a more-generalized array, we require |aCharN| be
197// null-terminated in all these functions.
198
199template <typename Char, size_t N>
200static void ExpectBadLeadUnit(const Char (&aCharN)[N]) {
201 ExpectInvalidCodePointHelper(aCharN, InvalidUtf8Reason::BadLeadUnit, 0xFF,
202 0xFF, 0xFFFFFFFF, 0xFF);
203}
204
205template <typename Char, size_t N>
206static void ExpectNotEnoughUnits(const Char (&aCharN)[N],
207 uint8_t aExpectedUnitsAvailable,
208 uint8_t aExpectedUnitsNeeded) {
209 ExpectInvalidCodePointHelper(aCharN, InvalidUtf8Reason::NotEnoughUnits,
210 aExpectedUnitsAvailable, aExpectedUnitsNeeded,
211 0xFFFFFFFF, 0xFF);
212}
213
214template <typename Char, size_t N>
215static void ExpectBadTrailingUnit(const Char (&aCharN)[N],
216 uint8_t aExpectedUnitsObserved) {
217 ExpectInvalidCodePointHelper(aCharN, InvalidUtf8Reason::BadTrailingUnit, 0xFF,
218 0xFF, 0xFFFFFFFF, aExpectedUnitsObserved);
219}
220
221template <typename Char, size_t N>
222static void ExpectNotShortestForm(const Char (&aCharN)[N],
223 char32_t aExpectedBadCodePoint,
224 uint8_t aExpectedUnitsObserved) {
225 ExpectInvalidCodePointHelper(aCharN, InvalidUtf8Reason::NotShortestForm, 0xFF,
226 0xFF, aExpectedBadCodePoint,
227 aExpectedUnitsObserved);
228}
229
230template <typename Char, size_t N>
231static void ExpectBadCodePoint(const Char (&aCharN)[N],
232 char32_t aExpectedBadCodePoint,
233 uint8_t aExpectedUnitsObserved) {
234 ExpectInvalidCodePointHelper(aCharN, InvalidUtf8Reason::BadCodePoint, 0xFF,
235 0xFF, aExpectedBadCodePoint,
236 aExpectedUnitsObserved);
237}
238
239static void TestIsUtf8() {
240 // Note we include the U+0000 NULL in this one -- and that's fine.
241 static const char asciiBytes[] = "How about a nice game of chess?";
242 MOZ_RELEASE_ASSERT(IsUtf8(Span(asciiBytes, std::size(asciiBytes))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(asciiBytes, std::size(asciiBytes))))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(Span(asciiBytes, std::size(asciiBytes)))))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("IsUtf8(Span(asciiBytes, std::size(asciiBytes)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 242); do { }
while (false); do { MOZ_CrashSequence(__null, 242); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
243
244 static const char endNonAsciiBytes[] = "Life is like a 🌯";
245 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes
) - 1)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes
) - 1))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes) - 1))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 246); do { }
while (false); do { MOZ_CrashSequence(__null, 246); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
246 IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes) - 1)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes
) - 1)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes
) - 1))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(Span(endNonAsciiBytes, std::size(endNonAsciiBytes) - 1))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 246); do { }
while (false); do { MOZ_CrashSequence(__null, 246); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
247
248 static const unsigned char badLeading[] = {0x80};
249 MOZ_RELEASE_ASSERT(!IsUtf8(AsChars(Span(badLeading, std::size(badLeading)))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(badLeading, std::size(badLeading
)))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(badLeading, std::size(badLeading
))))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(badLeading, std::size(badLeading))))",
"/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 249); do { } while
(false); do { MOZ_CrashSequence(__null, 249); __attribute__(
(nomerge)) ::abort(); } while (false); } } while (false)
;
250
251 // Byte-counts
252
253 // 1
254 static const char oneBytes[] = "A"; // U+0041 LATIN CAPITAL LETTER A
255 constexpr size_t oneBytesLen = std::size(oneBytes);
256 static_assert(oneBytesLen == 2, "U+0041 plus nul");
257 MOZ_RELEASE_ASSERT(IsUtf8(Span(oneBytes, oneBytesLen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(oneBytes, oneBytesLen)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsUtf8(Span(oneBytes, oneBytesLen
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(Span(oneBytes, oneBytesLen))", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 257); do { } while (false); do { MOZ_CrashSequence(__null, 257
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
258
259 // 2
260 static const char twoBytes[] = "؆"; // U+0606 ARABIC-INDIC CUBE ROOT
261 constexpr size_t twoBytesLen = std::size(twoBytes);
262 static_assert(twoBytesLen == 3, "U+0606 in two bytes plus nul");
263 MOZ_RELEASE_ASSERT(IsUtf8(Span(twoBytes, twoBytesLen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(twoBytes, twoBytesLen)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsUtf8(Span(twoBytes, twoBytesLen
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(Span(twoBytes, twoBytesLen))", "/root/firefox-clang/mfbt/tests/TestUtf8.cpp"
, 263); do { } while (false); do { MOZ_CrashSequence(__null, 263
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
264
265 ExpectValidCodePoint(twoBytes, 0x0606);
266
267 // 3
268 static const char threeBytes[] = "᨞"; // U+1A1E BUGINESE PALLAWA
269 constexpr size_t threeBytesLen = std::size(threeBytes);
270 static_assert(threeBytesLen == 4, "U+1A1E in three bytes plus nul");
271 MOZ_RELEASE_ASSERT(IsUtf8(Span(threeBytes, threeBytesLen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(threeBytes, threeBytesLen)))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsUtf8(Span(threeBytes, threeBytesLen))))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsUtf8(Span(threeBytes, threeBytesLen))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 271); do { }
while (false); do { MOZ_CrashSequence(__null, 271); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
272
273 ExpectValidCodePoint(threeBytes, 0x1A1E);
274
275 // 4
276 static const char fourBytes[] = "🁡"; // U+1F061 DOMINO TILE HORIZONTAL-06-06
277 constexpr size_t fourBytesLen = std::size(fourBytes);
278 static_assert(fourBytesLen == 5, "U+1F061 in four bytes plus nul");
279 MOZ_RELEASE_ASSERT(IsUtf8(Span(fourBytes, fourBytesLen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(fourBytes, fourBytesLen)))>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(IsUtf8(Span(fourBytes, fourBytesLen))))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsUtf8(Span(fourBytes, fourBytesLen))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 279); do { }
while (false); do { MOZ_CrashSequence(__null, 279); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
280
281 ExpectValidCodePoint(fourBytes, 0x1F061);
282
283 // Max code point
284 static const char maxCodePoint[] = "􏿿"; // U+10FFFF
285 constexpr size_t maxCodePointLen = std::size(maxCodePoint);
286 static_assert(maxCodePointLen == 5, "U+10FFFF in four bytes plus nul");
287 MOZ_RELEASE_ASSERT(IsUtf8(Span(maxCodePoint, maxCodePointLen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(Span(maxCodePoint, maxCodePointLen)))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsUtf8(Span(maxCodePoint, maxCodePointLen))))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsUtf8(Span(maxCodePoint, maxCodePointLen))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 287); do { }
while (false); do { MOZ_CrashSequence(__null, 287); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
288
289 ExpectValidCodePoint(maxCodePoint, 0x10FFFF);
290
291 // One past max code point
292 static const unsigned char onePastMaxCodePoint[] = {0xF4, 0x90, 0x80, 0x80,
293 0x0};
294 constexpr size_t onePastMaxCodePointLen = std::size(onePastMaxCodePoint);
295 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 296); do { }
while (false); do { MOZ_CrashSequence(__null, 296); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
296 !IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(onePastMaxCodePoint, onePastMaxCodePointLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 296); do { }
while (false); do { MOZ_CrashSequence(__null, 296); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
297
298 ExpectBadCodePoint(onePastMaxCodePoint, 0x110000, 4);
299
300 // Surrogate-related testing
301
302 // (Note that the various code unit sequences here are null-terminated to
303 // simplify life for ExpectValidCodePoint, which presumes null termination.)
304
305 static const unsigned char justBeforeSurrogates[] = {0xED, 0x9F, 0xBF, 0x0};
306 constexpr size_t justBeforeSurrogatesLen =
307 std::size(justBeforeSurrogates) - 1;
308 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 309); do { }
while (false); do { MOZ_CrashSequence(__null, 309); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
309 IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(AsChars(Span(justBeforeSurrogates, justBeforeSurrogatesLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 309); do { }
while (false); do { MOZ_CrashSequence(__null, 309); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
310
311 ExpectValidCodePoint(justBeforeSurrogates, 0xD7FF);
312
313 static const unsigned char leastSurrogate[] = {0xED, 0xA0, 0x80, 0x0};
314 constexpr size_t leastSurrogateLen = std::size(leastSurrogate) - 1;
315 MOZ_RELEASE_ASSERT(!IsUtf8(AsChars(Span(leastSurrogate, leastSurrogateLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(leastSurrogate, leastSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(leastSurrogate, leastSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(leastSurrogate, leastSurrogateLen)))",
"/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 315); do { } while
(false); do { MOZ_CrashSequence(__null, 315); __attribute__(
(nomerge)) ::abort(); } while (false); } } while (false)
;
316
317 ExpectBadCodePoint(leastSurrogate, 0xD800, 3);
318
319 static const unsigned char arbitraryHighSurrogate[] = {0xED, 0xA2, 0x87, 0x0};
320 constexpr size_t arbitraryHighSurrogateLen =
321 std::size(arbitraryHighSurrogate) - 1;
322 MOZ_RELEASE_ASSERT(!IsUtf8(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 323); do { }
while (false); do { MOZ_CrashSequence(__null, 323); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
323 AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8( AsChars(Span(arbitraryHighSurrogate, arbitraryHighSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 323); do { }
while (false); do { MOZ_CrashSequence(__null, 323); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
324
325 ExpectBadCodePoint(arbitraryHighSurrogate, 0xD887, 3);
326
327 static const unsigned char arbitraryLowSurrogate[] = {0xED, 0xB7, 0xAF, 0x0};
328 constexpr size_t arbitraryLowSurrogateLen =
329 std::size(arbitraryLowSurrogate) - 1;
330 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 331); do { }
while (false); do { MOZ_CrashSequence(__null, 331); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
331 !IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(arbitraryLowSurrogate, arbitraryLowSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 331); do { }
while (false); do { MOZ_CrashSequence(__null, 331); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
332
333 ExpectBadCodePoint(arbitraryLowSurrogate, 0xDDEF, 3);
334
335 static const unsigned char greatestSurrogate[] = {0xED, 0xBF, 0xBF, 0x0};
336 constexpr size_t greatestSurrogateLen = std::size(greatestSurrogate) - 1;
337 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 338); do { }
while (false); do { MOZ_CrashSequence(__null, 338); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
338 !IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsUtf8(AsChars(Span(greatestSurrogate, greatestSurrogateLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 338); do { }
while (false); do { MOZ_CrashSequence(__null, 338); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
339
340 ExpectBadCodePoint(greatestSurrogate, 0xDFFF, 3);
341
342 static const unsigned char justAfterSurrogates[] = {0xEE, 0x80, 0x80, 0x0};
343 constexpr size_t justAfterSurrogatesLen = std::size(justAfterSurrogates) - 1;
344 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 345); do { }
while (false); do { MOZ_CrashSequence(__null, 345); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
345 IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen))))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsUtf8(AsChars(Span(justAfterSurrogates, justAfterSurrogatesLen)))"
, "/root/firefox-clang/mfbt/tests/TestUtf8.cpp", 345); do { }
while (false); do { MOZ_CrashSequence(__null, 345); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
346
347 ExpectValidCodePoint(justAfterSurrogates, 0xE000);
348}
349
350static void TestDecodeOneValidUtf8CodePoint() {
351 // NOTE: DecodeOneUtf8CodePoint decodes only *non*-ASCII code points that
352 // consist of multiple code units, so there are no ASCII tests below.
353
354 // Length two.
355
356 ExpectValidCodePoint("€", 0x80); // <control>
357 ExpectValidCodePoint("©", 0xA9); // COPYRIGHT SIGN
358 ExpectValidCodePoint("¶", 0xB6); // PILCROW SIGN
359 ExpectValidCodePoint("¾", 0xBE); // VULGAR FRACTION THREE QUARTERS
360 ExpectValidCodePoint("÷", 0xF7); // DIVISION SIGN
361 ExpectValidCodePoint("ÿ", 0xFF); // LATIN SMALL LETTER Y WITH DIAERESIS
362 ExpectValidCodePoint("Ā", 0x100); // LATIN CAPITAL LETTER A WITH MACRON
363 ExpectValidCodePoint("IJ", 0x132); // LATIN CAPITAL LETTER LIGATURE IJ
364 ExpectValidCodePoint("ͼ", 0x37C); // GREEK SMALL DOTTED LUNATE SIGMA SYMBOL
365 ExpectValidCodePoint("Ӝ",
366 0x4DC); // CYRILLIC CAPITAL LETTER ZHE WITTH DIAERESIS
367 ExpectValidCodePoint("۩", 0x6E9); // ARABIC PLACE OF SAJDAH
368 ExpectValidCodePoint("߿", 0x7FF); // <not assigned>
369
370 // Length three.
371
372 ExpectValidCodePoint("ࠀ", 0x800); // SAMARITAN LETTER ALAF
373 ExpectValidCodePoint("ࡁ", 0x841); // MANDAIC LETTER AB
374 ExpectValidCodePoint("ࣿ", 0x8FF); // ARABIC MARK SIDEWAYS NOON GHUNNA
375 ExpectValidCodePoint("ஆ", 0xB86); // TAMIL LETTER AA
376 ExpectValidCodePoint("༃",
377 0xF03); // TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
378 ExpectValidCodePoint(
379 "࿉",
380 0xFC9); // TIBETAN SYMBOL NOR BU (but on my system it really looks like
381 // SOFT-SERVE ICE CREAM FROM ABOVE THE PLANE if you ask me)
382 ExpectValidCodePoint("ဪ", 0x102A); // MYANMAR LETTER AU
383 ExpectValidCodePoint("ᚏ", 0x168F); // OGHAM LETTER RUIS
384 ExpectValidCodePoint("\xE2\x80\xA8", 0x2028); // (the hated) LINE SEPARATOR
385 ExpectValidCodePoint("\xE2\x80\xA9",
386 0x2029); // (the hated) PARAGRAPH SEPARATOR
387 ExpectValidCodePoint("☬", 0x262C); // ADI SHAKTI
388 ExpectValidCodePoint("㊮", 0x32AE); // CIRCLED IDEOGRAPH RESOURCE
389 ExpectValidCodePoint("㏖", 0x33D6); // SQUARE MOL
390 ExpectValidCodePoint("ꔄ", 0xA504); // VAI SYLLABLE WEEN
391 ExpectValidCodePoint("ퟕ", 0xD7D5); // HANGUL JONGSEONG RIEUL-SSANGKIYEOK
392 ExpectValidCodePoint("퟿", 0xD7FF); // <not assigned>
393 ExpectValidCodePoint("", 0xE000); // <Private Use>
394 ExpectValidCodePoint("鱗", 0xF9F2); // CJK COMPATIBILITY IDEOGRAPH-F9F
395 ExpectValidCodePoint(
396 "﷽", 0xFDFD); // ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHHHEEEEM
397 ExpectValidCodePoint("￿", 0xFFFF); // <not assigned>
398
399 // Length four.
400 ExpectValidCodePoint("𐀀", 0x10000); // LINEAR B SYLLABLE B008 A
401 ExpectValidCodePoint("𔑀", 0x14440); // ANATOLIAN HIEROGLYPH A058
402 ExpectValidCodePoint("𝛗", 0x1D6D7); // MATHEMATICAL BOLD SMALL PHI
403 ExpectValidCodePoint("💩", 0x1F4A9); // PILE OF POO
404 ExpectValidCodePoint("🔫", 0x1F52B); // PISTOL
405 ExpectValidCodePoint("🥌", 0x1F94C); // CURLING STONE
406 ExpectValidCodePoint("🥏", 0x1F94F); // FLYING DISC
407 ExpectValidCodePoint("𠍆", 0x20346); // CJK UNIFIED IDEOGRAPH-20346
408 ExpectValidCodePoint("𡠺", 0x2183A); // CJK UNIFIED IDEOGRAPH-2183A
409 ExpectValidCodePoint("񁟶", 0x417F6); // <not assigned>
410 ExpectValidCodePoint("񾠶", 0x7E836); // <not assigned>
411 ExpectValidCodePoint("󾽧", 0xFEF67); // <Plane 15 Private Use>
412 ExpectValidCodePoint("􏿿", 0x10FFFF); //
413}
414
415static void TestDecodeBadLeadUnit() {
416 // These tests are actually exhaustive.
417
418 unsigned char badLead[] = {'\0', '\0'};
419
420 for (uint8_t lead : IntegerRange(0b1000'0000, 0b1100'0000)) {
421 badLead[0] = lead;
422 ExpectBadLeadUnit(badLead);
423 }
424
425 {
426 uint8_t lead = 0b1111'1000;
427 do {
428 badLead[0] = lead;
429 ExpectBadLeadUnit(badLead);
430 if (lead == 0b1111'1111) {
431 break;
432 }
433
434 lead++;
435 } while (true);
436 }
437}
438
439static void TestTooFewOrBadTrailingUnits() {
440 // Lead unit indicates a two-byte code point.
441
442 char truncatedTwo[] = {'\0', '\0'};
443 char badTrailTwo[] = {'\0', '\0', '\0'};
444
445 for (uint8_t lead : IntegerRange(0b1100'0000, 0b1110'0000)) {
446 truncatedTwo[0] = lead;
447 ExpectNotEnoughUnits(truncatedTwo, 1, 2);
448
449 badTrailTwo[0] = lead;
450 for (uint8_t trail : IntegerRange(0b0000'0000, 0b1000'0000)) {
451 badTrailTwo[1] = trail;
452 ExpectBadTrailingUnit(badTrailTwo, 2);
453 }
454
455 for (uint8_t trail : IntegerRange(0b1100'0000, 0b1111'1111)) {
456 badTrailTwo[1] = trail;
457 ExpectBadTrailingUnit(badTrailTwo, 2);
458 }
459 }
460
461 // Lead unit indicates a three-byte code point.
462
463 char truncatedThreeOne[] = {'\0', '\0'};
464 char truncatedThreeTwo[] = {'\0', '\0', '\0'};
465 unsigned char badTrailThree[] = {'\0', '\0', '\0', '\0'};
466
467 for (uint8_t lead : IntegerRange(0b1110'0000, 0b1111'0000)) {
468 truncatedThreeOne[0] = lead;
469 ExpectNotEnoughUnits(truncatedThreeOne, 1, 3);
470
471 truncatedThreeTwo[0] = lead;
472 ExpectNotEnoughUnits(truncatedThreeTwo, 2, 3);
473
474 badTrailThree[0] = lead;
475 badTrailThree[2] = 0b1011'1111; // make valid to test overreads
476 for (uint8_t mid : IntegerRange(0b0000'0000, 0b1000'0000)) {
477 badTrailThree[1] = mid;
478 ExpectBadTrailingUnit(badTrailThree, 2);
479 }
480 {
481 uint8_t mid = 0b1100'0000;
482 do {
483 badTrailThree[1] = mid;
484 ExpectBadTrailingUnit(badTrailThree, 2);
485 if (mid == 0b1111'1111) {
486 break;
487 }
488
489 mid++;
490 } while (true);
491 }
492
493 badTrailThree[1] = 0b1011'1111;
494 for (uint8_t last : IntegerRange(0b0000'0000, 0b1000'0000)) {
495 badTrailThree[2] = last;
496 ExpectBadTrailingUnit(badTrailThree, 3);
497 }
498 {
499 uint8_t last = 0b1100'0000;
500 do {
501 badTrailThree[2] = last;
502 ExpectBadTrailingUnit(badTrailThree, 3);
503 if (last == 0b1111'1111) {
504 break;
505 }
506
507 last++;
508 } while (true);
509 }
510 }
511
512 // Lead unit indicates a four-byte code point.
513
514 char truncatedFourOne[] = {'\0', '\0'};
515 char truncatedFourTwo[] = {'\0', '\0', '\0'};
516 char truncatedFourThree[] = {'\0', '\0', '\0', '\0'};
517
518 unsigned char badTrailFour[] = {'\0', '\0', '\0', '\0', '\0'};
519
520 for (uint8_t lead : IntegerRange(0b1111'0000, 0b1111'1000)) {
521 truncatedFourOne[0] = lead;
522 ExpectNotEnoughUnits(truncatedFourOne, 1, 4);
523
524 truncatedFourTwo[0] = lead;
525 ExpectNotEnoughUnits(truncatedFourTwo, 2, 4);
526
527 truncatedFourThree[0] = lead;
528 ExpectNotEnoughUnits(truncatedFourThree, 3, 4);
529
530 badTrailFour[0] = lead;
531 badTrailFour[2] = badTrailFour[3] = 0b1011'1111; // test for overreads
532 for (uint8_t second : IntegerRange(0b0000'0000, 0b1000'0000)) {
533 badTrailFour[1] = second;
534 ExpectBadTrailingUnit(badTrailFour, 2);
535 }
536 {
537 uint8_t second = 0b1100'0000;
538 do {
539 badTrailFour[1] = second;
540 ExpectBadTrailingUnit(badTrailFour, 2);
541 if (second == 0b1111'1111) {
542 break;
543 }
544
545 second++;
546 } while (true);
547 }
548
549 badTrailFour[1] = badTrailFour[3] = 0b1011'1111; // test for overreads
550 for (uint8_t third : IntegerRange(0b0000'0000, 0b1000'0000)) {
551 badTrailFour[2] = third;
552 ExpectBadTrailingUnit(badTrailFour, 3);
553 }
554 {
555 uint8_t third = 0b1100'0000;
556 do {
557 badTrailFour[2] = third;
558 ExpectBadTrailingUnit(badTrailFour, 3);
559 if (third == 0b1111'1111) {
560 break;
561 }
562
563 third++;
564 } while (true);
565 }
566
567 badTrailFour[2] = 0b1011'1111;
568 for (uint8_t fourth : IntegerRange(0b0000'0000, 0b1000'0000)) {
569 badTrailFour[3] = fourth;
570 ExpectBadTrailingUnit(badTrailFour, 4);
571 }
572 {
573 uint8_t fourth = 0b1100'0000;
574 do {
575 badTrailFour[3] = fourth;
576 ExpectBadTrailingUnit(badTrailFour, 4);
577 if (fourth == 0b1111'1111) {
578 break;
579 }
580
581 fourth++;
582 } while (true);
583 }
584 }
585}
586
587static void TestBadSurrogate() {
588 // These tests are actually exhaustive.
589
590 ExpectValidCodePoint("\xED\x9F\xBF", 0xD7FF); // last before surrogates
591 ExpectValidCodePoint("\xEE\x80\x80", 0xE000); // first after surrogates
592
593 // First invalid surrogate encoding is { 0xED, 0xA0, 0x80 }. Last invalid
594 // surrogate encoding is { 0xED, 0xBF, 0xBF }.
595
596 char badSurrogate[] = {'\xED', '\0', '\0', '\0'};
597
598 for (char32_t c = 0xD800; c < 0xE000; c++) {
599 badSurrogate[1] = 0b1000'0000 ^ ((c & 0b1111'1100'0000) >> 6);
600 badSurrogate[2] = 0b1000'0000 ^ ((c & 0b0000'0011'1111));
601
602 ExpectBadCodePoint(badSurrogate, c, 3);
603 }
604}
605
606static void TestBadTooBig() {
607 // These tests are actually exhaustive.
608
609 ExpectValidCodePoint("\xF4\x8F\xBF\xBF", 0x10'FFFF); // last code point
610
611 // Four-byte code points are
612 //
613 // 0b1111'0xxx 0b10xx'xxxx 0b10xx'xxxx 0b10xx'xxxx
614 //
615 // with 3 + 6 + 6 + 6 == 21 unconstrained bytes, so the structurally
616 // representable limit (exclusive) is 2**21 - 1 == 2097152.
617
618 char tooLargeCodePoint[] = {'\0', '\0', '\0', '\0', '\0'};
619
620 for (char32_t c = 0x11'0000; c < (1 << 21); c++) {
621 tooLargeCodePoint[0] =
622 0b1111'0000 ^ ((c & 0b1'1100'0000'0000'0000'0000) >> 18);
623 tooLargeCodePoint[1] =
624 0b1000'0000 ^ ((c & 0b0'0011'1111'0000'0000'0000) >> 12);
625 tooLargeCodePoint[2] =
626 0b1000'0000 ^ ((c & 0b0'0000'0000'1111'1100'0000) >> 6);
627 tooLargeCodePoint[3] = 0b1000'0000 ^ ((c & 0b0'0000'0000'0000'0011'1111));
628
629 ExpectBadCodePoint(tooLargeCodePoint, c, 4);
630 }
631}
632
633static void TestBadCodePoint() {
634 TestBadSurrogate();
635 TestBadTooBig();
636}
637
638static void TestNotShortestForm() {
639 {
640 // One-byte in two-byte.
641
642 char oneInTwo[] = {'\0', '\0', '\0'};
643
644 for (char32_t c = '\0'; c < 0x80; c++) {
645 oneInTwo[0] = 0b1100'0000 ^ ((c & 0b0111'1100'0000) >> 6);
646 oneInTwo[1] = 0b1000'0000 ^ ((c & 0b0000'0011'1111));
647
648 ExpectNotShortestForm(oneInTwo, c, 2);
649 }
650
651 // One-byte in three-byte.
652
653 char oneInThree[] = {'\0', '\0', '\0', '\0'};
654
655 for (char32_t c = '\0'; c < 0x80; c++) {
656 oneInThree[0] = 0b1110'0000 ^ ((c & 0b1111'0000'0000'0000) >> 12);
657 oneInThree[1] = 0b1000'0000 ^ ((c & 0b0000'1111'1100'0000) >> 6);
658 oneInThree[2] = 0b1000'0000 ^ ((c & 0b0000'0000'0011'1111));
659
660 ExpectNotShortestForm(oneInThree, c, 3);
661 }
662
663 // One-byte in four-byte.
664
665 char oneInFour[] = {'\0', '\0', '\0', '\0', '\0'};
666
667 for (char32_t c = '\0'; c < 0x80; c++) {
668 oneInFour[0] = 0b1111'0000 ^ ((c & 0b1'1100'0000'0000'0000'0000) >> 18);
669 oneInFour[1] = 0b1000'0000 ^ ((c & 0b0'0011'1111'0000'0000'0000) >> 12);
670 oneInFour[2] = 0b1000'0000 ^ ((c & 0b0'0000'0000'1111'1100'0000) >> 6);
671 oneInFour[3] = 0b1000'0000 ^ ((c & 0b0'0000'0000'0000'0011'1111));
672
673 ExpectNotShortestForm(oneInFour, c, 4);
674 }
675 }
676
677 {
678 // Two-byte in three-byte.
679
680 char twoInThree[] = {'\0', '\0', '\0', '\0'};
681
682 for (char32_t c = 0x80; c < 0x800; c++) {
683 twoInThree[0] = 0b1110'0000 ^ ((c & 0b1111'0000'0000'0000) >> 12);
684 twoInThree[1] = 0b1000'0000 ^ ((c & 0b0000'1111'1100'0000) >> 6);
685 twoInThree[2] = 0b1000'0000 ^ ((c & 0b0000'0000'0011'1111));
686
687 ExpectNotShortestForm(twoInThree, c, 3);
688 }
689
690 // Two-byte in four-byte.
691
692 char twoInFour[] = {'\0', '\0', '\0', '\0', '\0'};
693
694 for (char32_t c = 0x80; c < 0x800; c++) {
695 twoInFour[0] = 0b1111'0000 ^ ((c & 0b1'1100'0000'0000'0000'0000) >> 18);
696 twoInFour[1] = 0b1000'0000 ^ ((c & 0b0'0011'1111'0000'0000'0000) >> 12);
697 twoInFour[2] = 0b1000'0000 ^ ((c & 0b0'0000'0000'1111'1100'0000) >> 6);
698 twoInFour[3] = 0b1000'0000 ^ ((c & 0b0'0000'0000'0000'0011'1111));
699
700 ExpectNotShortestForm(twoInFour, c, 4);
701 }
702 }
703
704 {
705 // Three-byte in four-byte.
706
707 char threeInFour[] = {'\0', '\0', '\0', '\0', '\0'};
708
709 for (char32_t c = 0x800; c < 0x1'0000; c++) {
710 threeInFour[0] = 0b1111'0000 ^ ((c & 0b1'1100'0000'0000'0000'0000) >> 18);
711 threeInFour[1] = 0b1000'0000 ^ ((c & 0b0'0011'1111'0000'0000'0000) >> 12);
712 threeInFour[2] = 0b1000'0000 ^ ((c & 0b0'0000'0000'1111'1100'0000) >> 6);
713 threeInFour[3] = 0b1000'0000 ^ ((c & 0b0'0000'0000'0000'0011'1111));
714
715 ExpectNotShortestForm(threeInFour, c, 4);
716 }
717 }
718}
719
720static void TestDecodeOneInvalidUtf8CodePoint() {
721 TestDecodeBadLeadUnit();
722 TestTooFewOrBadTrailingUnits();
723 TestBadCodePoint();
724 TestNotShortestForm();
725}
726
727static void TestDecodeOneUtf8CodePoint() {
728 TestDecodeOneValidUtf8CodePoint();
729 TestDecodeOneInvalidUtf8CodePoint();
730}
731
732int main() {
733 TestUtf8Unit();
734 TestIsUtf8();
735 TestDecodeOneUtf8CodePoint();
736 return 0;
737}