Bug Summary

File:root/firefox-clang/intl/icu/source/i18n/scriptset.cpp
Warning:line 111, column 17
The left expression of the compound assignment uses uninitialized memory

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 scriptset.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/config/external/icu/i18n -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -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 -D U_I18N_IMPLEMENTATION -D _LIBCPP_DISABLE_DEPRECATION_WARNINGS -D U_USING_ICU_NAMESPACE=0 -D U_NO_DEFAULT_INCLUDE_UTF_HEADERS=1 -D U_HIDE_OBSOLETE_UTF_OLD_H=1 -D UCONFIG_NO_LEGACY_CONVERSION -D UCONFIG_NO_TRANSLITERATION -D UCONFIG_NO_REGULAR_EXPRESSIONS -D UCONFIG_NO_BREAK_ITERATION -D UCONFIG_NO_IDNA -D UCONFIG_NO_MF2 -D UCONFIG_NO_NORMALIZATION -D UCONFIG_NO_COLLATION -D U_CHARSET_IS_UTF8 -D UNISTR_FROM_CHAR_EXPLICIT=explicit -D UNISTR_FROM_STRING_EXPLICIT=explicit -D U_ENABLE_DYLOAD=0 -D U_DEBUG=1 -I /root/firefox-clang/config/external/icu/i18n -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/config/external/icu/i18n -I /root/firefox-clang/intl/icu/source/common -I /root/firefox-clang/mfbt/double-conversion -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -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 -Wno-comma -Wno-implicit-const-int-float-conversion -Wno-macro-redefined -Wno-microsoft-include -Wno-tautological-unsigned-enum-zero-compare -Wno-unreachable-code-loop-increment -Wno-unreachable-code-return -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -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/intl/icu/source/i18n/scriptset.cpp
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4**********************************************************************
5* Copyright (C) 2014, International Business Machines
6* Corporation and others. All Rights Reserved.
7**********************************************************************
8*
9* scriptset.cpp
10*
11* created on: 2013 Jan 7
12* created by: Andy Heninger
13*/
14
15#include "unicode/utypes.h"
16
17#include "unicode/uchar.h"
18#include "unicode/unistr.h"
19
20#include "scriptset.h"
21#include "uassert.h"
22#include "cmemory.h"
23
24U_NAMESPACE_BEGINnamespace icu_78 {
25
26//----------------------------------------------------------------------------
27//
28// ScriptSet implementation
29//
30//----------------------------------------------------------------------------
31ScriptSet::ScriptSet() {
32 uprv_memset(bits, 0, sizeof(bits)):: memset(bits, 0, sizeof(bits));
33}
34
35ScriptSet::~ScriptSet() {
36}
37
38ScriptSet::ScriptSet(const ScriptSet &other) {
39 *this = other;
40}
41
42ScriptSet & ScriptSet::operator =(const ScriptSet &other) {
43 if (this != &other) {
44 uprv_memcpy(bits, other.bits, sizeof(bits))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(static_cast <bool> (bits != __null) ? void (0) : __assert_fail
("bits != __null", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__)); (static_cast <bool> (other.bits
!= __null) ? void (0) : __assert_fail ("other.bits != __null"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
)); clang diagnostic pop :: memcpy(bits, other.bits, sizeof(
bits)); } while (false)
;
45 }
46 return *this;
47}
48
49bool ScriptSet::operator == (const ScriptSet &other) const {
50 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
51 if (bits[i] != other.bits[i]) {
52 return false;
53 }
54 }
55 return true;
56}
57
58UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const {
59 if (U_FAILURE(status)) {
60 return false;
61 }
62 if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) {
63 status = U_ILLEGAL_ARGUMENT_ERROR;
64 return false;
65 }
66 uint32_t index = script / 32;
67 uint32_t bit = 1 << (script & 31);
68 return ((bits[index] & bit) != 0);
69}
70
71
72ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) {
73 if (U_FAILURE(status)) {
74 return *this;
75 }
76 if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) {
77 status = U_ILLEGAL_ARGUMENT_ERROR;
78 return *this;
79 }
80 uint32_t index = script / 32;
81 uint32_t bit = 1 << (script & 31);
82 bits[index] |= bit;
83 return *this;
84}
85
86ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) {
87 if (U_FAILURE(status)) {
88 return *this;
89 }
90 if (script < 0 || static_cast<int32_t>(script) >= SCRIPT_LIMIT) {
91 status = U_ILLEGAL_ARGUMENT_ERROR;
92 return *this;
93 }
94 uint32_t index = script / 32;
95 uint32_t bit = 1 << (script & 31);
96 bits[index] &= ~bit;
97 return *this;
98}
99
100
101
102ScriptSet &ScriptSet::Union(const ScriptSet &other) {
103 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
104 bits[i] |= other.bits[i];
105 }
106 return *this;
107}
108
109ScriptSet &ScriptSet::intersect(const ScriptSet &other) {
110 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
2
'i' initialized to 0
3
Loop condition is true. Entering loop body
111 bits[i] &= other.bits[i];
4
The left expression of the compound assignment uses uninitialized memory
112 }
113 return *this;
114}
115
116ScriptSet &ScriptSet::intersect(UScriptCode script, UErrorCode &status) {
117 ScriptSet t;
118 t.set(script, status);
119 if (U_SUCCESS(status)) {
120 this->intersect(t);
121 }
122 return *this;
123}
124
125UBool ScriptSet::intersects(const ScriptSet &other) const {
126 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
127 if ((bits[i] & other.bits[i]) != 0) {
128 return true;
129 }
130 }
131 return false;
132}
133
134UBool ScriptSet::contains(const ScriptSet &other) const {
135 ScriptSet t(*this);
136 t.intersect(other);
1
Calling 'ScriptSet::intersect'
137 return (t == other);
138}
139
140
141ScriptSet &ScriptSet::setAll() {
142 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
143 bits[i] = 0xffffffffu;
144 }
145 return *this;
146}
147
148
149ScriptSet &ScriptSet::resetAll() {
150 uprv_memset(bits, 0, sizeof(bits)):: memset(bits, 0, sizeof(bits));
151 return *this;
152}
153
154int32_t ScriptSet::countMembers() const {
155 // This bit counter is good for sparse numbers of '1's, which is
156 // very much the case that we will usually have.
157 int32_t count = 0;
158 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
159 uint32_t x = bits[i];
160 while (x > 0) {
161 count++;
162 x &= (x - 1); // and off the least significant one bit.
163 }
164 }
165 return count;
166}
167
168int32_t ScriptSet::hashCode() const {
169 int32_t hash = 0;
170 for (int32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
171 hash ^= bits[i];
172 }
173 return hash;
174}
175
176int32_t ScriptSet::nextSetBit(int32_t fromIndex) const {
177 // TODO: Wants a better implementation.
178 if (fromIndex < 0) {
179 return -1;
180 }
181 UErrorCode status = U_ZERO_ERROR;
182 for (int32_t scriptIndex = fromIndex; scriptIndex < SCRIPT_LIMIT; scriptIndex++) {
183 if (test(static_cast<UScriptCode>(scriptIndex), status)) {
184 return scriptIndex;
185 }
186 }
187 return -1;
188}
189
190UBool ScriptSet::isEmpty() const {
191 for (uint32_t i=0; i<UPRV_LENGTHOF(bits)(int32_t)(sizeof(bits)/sizeof((bits)[0])); i++) {
192 if (bits[i] != 0) {
193 return false;
194 }
195 }
196 return true;
197}
198
199UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const {
200 UBool firstTime = true;
201 for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) {
202 if (!firstTime) {
203 dest.append(static_cast<char16_t>(0x20));
204 }
205 firstTime = false;
206 const char* scriptName = uscript_getShortName(static_cast<UScriptCode>(i));
207 dest.append(UnicodeString(scriptName, -1, US_INVicu::UnicodeString::kInvariant));
208 }
209 return dest;
210}
211
212ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode &status) {
213 resetAll();
214 if (U_FAILURE(status)) {
215 return *this;
216 }
217 UnicodeString oneScriptName;
218 for (int32_t i=0; i<scriptString.length();) {
219 UChar32 c = scriptString.char32At(i);
220 i = scriptString.moveIndex32(i, 1);
221 if (!u_isUWhiteSpace(c)) {
222 oneScriptName.append(c);
223 if (i < scriptString.length()) {
224 continue;
225 }
226 }
227 if (oneScriptName.length() > 0) {
228 char buf[40];
229 oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INVicu::UnicodeString::kInvariant);
230 buf[sizeof(buf)-1] = 0;
231 int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf);
232 if (sc == UCHAR_INVALID_CODE) {
233 status = U_ILLEGAL_ARGUMENT_ERROR;
234 } else {
235 this->set(static_cast<UScriptCode>(sc), status);
236 }
237 if (U_FAILURE(status)) {
238 return *this;
239 }
240 oneScriptName.remove();
241 }
242 }
243 return *this;
244}
245
246void ScriptSet::setScriptExtensions(UChar32 codePoint, UErrorCode& status) {
247 if (U_FAILURE(status)) { return; }
248 static const int32_t FIRST_GUESS_SCRIPT_CAPACITY = 20;
249 MaybeStackArray<UScriptCode,FIRST_GUESS_SCRIPT_CAPACITY> scripts;
250 UErrorCode internalStatus = U_ZERO_ERROR;
251 int32_t script_count = -1;
252
253 while (true) {
254 script_count = uscript_getScriptExtensions(
255 codePoint, scripts.getAlias(), scripts.getCapacity(), &internalStatus);
256 if (internalStatus == U_BUFFER_OVERFLOW_ERROR) {
257 // Need to allocate more space
258 if (scripts.resize(script_count) == nullptr) {
259 status = U_MEMORY_ALLOCATION_ERROR;
260 return;
261 }
262 internalStatus = U_ZERO_ERROR;
263 } else {
264 break;
265 }
266 }
267
268 // Check if we failed for some reason other than buffer overflow
269 if (U_FAILURE(internalStatus)) {
270 status = internalStatus;
271 return;
272 }
273
274 // Load the scripts into the ScriptSet and return
275 for (int32_t i = 0; i < script_count; i++) {
276 this->set(scripts[i], status);
277 if (U_FAILURE(status)) { return; }
278 }
279}
280
281U_NAMESPACE_END}
282
283U_CAPIextern "C" UBool U_EXPORT2
284uhash_equalsScriptSet(const UElement key1, const UElement key2) {
285 icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
286 icu::ScriptSet *s2 = static_cast<icu::ScriptSet *>(key2.pointer);
287 return (*s1 == *s2);
288}
289
290U_CAPIextern "C" int32_t U_EXPORT2
291uhash_compareScriptSet(UElement key0, UElement key1) {
292 icu::ScriptSet *s0 = static_cast<icu::ScriptSet *>(key0.pointer);
293 icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
294 int32_t diff = s0->countMembers() - s1->countMembers();
295 if (diff != 0) return diff;
296 int32_t i0 = s0->nextSetBit(0);
297 int32_t i1 = s1->nextSetBit(0);
298 while ((diff = i0-i1) == 0 && i0 > 0) {
299 i0 = s0->nextSetBit(i0+1);
300 i1 = s1->nextSetBit(i1+1);
301 }
302 return diff;
303}
304
305U_CAPIextern "C" int32_t U_EXPORT2
306uhash_hashScriptSet(const UElement key) {
307 icu::ScriptSet *s = static_cast<icu::ScriptSet *>(key.pointer);
308 return s->hashCode();
309}
310
311U_CAPIextern "C" void U_EXPORT2
312uhash_deleteScriptSet(void *obj) {
313 icu::ScriptSet *s = static_cast<icu::ScriptSet *>(obj);
314 delete s;
315}