Bug Summary

File:out/../deps/icu-small/source/common/utrie2.cpp
Warning:line 577, column 83
Array access (from variable 'idx') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name utrie2.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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D U_COMMON_IMPLEMENTATION=1 -D U_ATTRIBUTE_DEPRECATED= -D _CRT_SECURE_NO_DEPRECATE= -D U_STATIC_IMPLEMENTATION=1 -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/icu-small/source/common -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-deprecated-declarations -Wno-strict-aliasing -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/icu-small/source/common/utrie2.cpp
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4******************************************************************************
5*
6* Copyright (C) 2001-2014, International Business Machines
7* Corporation and others. All Rights Reserved.
8*
9******************************************************************************
10* file name: utrie2.cpp
11* encoding: UTF-8
12* tab size: 8 (not used)
13* indentation:4
14*
15* created on: 2008aug16 (starting from a copy of utrie.c)
16* created by: Markus W. Scherer
17*
18* This is a common implementation of a Unicode trie.
19* It is a kind of compressed, serializable table of 16- or 32-bit values associated with
20* Unicode code points (0..0x10ffff).
21* This is the second common version of a Unicode trie (hence the name UTrie2).
22* See utrie2.h for a comparison.
23*
24* This file contains only the runtime and enumeration code, for read-only access.
25* See utrie2_builder.c for the builder code.
26*/
27#include "unicode/utypes.h"
28#ifdef UCPTRIE_DEBUG
29#include "unicode/umutablecptrie.h"
30#endif
31#include "unicode/utf.h"
32#include "unicode/utf8.h"
33#include "unicode/utf16.h"
34#include "cmemory.h"
35#include "utrie2.h"
36#include "utrie2_impl.h"
37#include "uassert.h"
38
39/* Public UTrie2 API implementation ----------------------------------------- */
40
41static uint32_t
42get32(const UNewTrie2 *trie, UChar32 c, UBool fromLSCP) {
43 int32_t i2, block;
44
45 if(c>=trie->highStart && (!U_IS_LEAD(c)(((c)&0xfffffc00)==0xd800) || fromLSCP)) {
46 return trie->data[trie->dataLength-UTRIE2_DATA_GRANULARITY];
47 }
48
49 if(U_IS_LEAD(c)(((c)&0xfffffc00)==0xd800) && fromLSCP) {
50 i2=(UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2))+
51 (c>>UTRIE2_SHIFT_2);
52 } else {
53 i2=trie->index1[c>>UTRIE2_SHIFT_1]+
54 ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK);
55 }
56 block=trie->index2[i2];
57 return trie->data[block+(c&UTRIE2_DATA_MASK)];
58}
59
60U_CAPIextern "C" uint32_t U_EXPORT2
61utrie2_get32utrie2_get32_71(const UTrie2 *trie, UChar32 c) {
62 if(trie->data16!=NULL__null) {
63 return UTRIE2_GET16(trie, c)((trie))->index[((uint32_t)((c))<0xd800 ? (((int32_t)((
((trie))->index)[(0)+(((c))>>UTRIE2_SHIFT_2)]) <<
UTRIE2_INDEX_SHIFT)+ (((c))&UTRIE2_DATA_MASK)) : (uint32_t
)((c))<=0xffff ? (((int32_t)((((trie))->index)[(((c))<=
0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2
) : 0)+(((c))>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT
)+ (((c))&UTRIE2_DATA_MASK)) : (uint32_t)((c))>0x10ffff
? ((trie)->indexLength)+UTRIE2_BAD_UTF8_DATA_OFFSET : ((c
))>=((trie))->highStart ? ((trie))->highValueIndex :
(((int32_t)((((trie))->index)[ (((trie))->index)[(UTRIE2_INDEX_1_OFFSET
-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+ (((c))>>UTRIE2_SHIFT_1
)]+ ((((c))>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK)])
<<UTRIE2_INDEX_SHIFT)+ (((c))&UTRIE2_DATA_MASK)))]
;
64 } else if(trie->data32!=NULL__null) {
65 return UTRIE2_GET32(trie, c)((trie))->data32[((uint32_t)((c))<0xd800 ? (((int32_t)(
(((trie))->index)[(0)+(((c))>>UTRIE2_SHIFT_2)]) <<
UTRIE2_INDEX_SHIFT)+ (((c))&UTRIE2_DATA_MASK)) : (uint32_t
)((c))<=0xffff ? (((int32_t)((((trie))->index)[(((c))<=
0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2
) : 0)+(((c))>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT
)+ (((c))&UTRIE2_DATA_MASK)) : (uint32_t)((c))>0x10ffff
? (0)+UTRIE2_BAD_UTF8_DATA_OFFSET : ((c))>=((trie))->highStart
? ((trie))->highValueIndex : (((int32_t)((((trie))->index
)[ (((trie))->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ (((c))>>UTRIE2_SHIFT_1)]+ ((((c))>>UTRIE2_SHIFT_2
)&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT)+ (((
c))&UTRIE2_DATA_MASK)))]
;
66 } else if((uint32_t)c>0x10ffff) {
67 return trie->errorValue;
68 } else {
69 return get32(trie->newTrie, c, TRUE1);
70 }
71}
72
73U_CAPIextern "C" uint32_t U_EXPORT2
74utrie2_get32FromLeadSurrogateCodeUnitutrie2_get32FromLeadSurrogateCodeUnit_71(const UTrie2 *trie, UChar32 c) {
75 if(!U_IS_LEAD(c)(((c)&0xfffffc00)==0xd800)) {
76 return trie->errorValue;
77 }
78 if(trie->data16!=NULL__null) {
79 return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, c)((trie))->index[(((int32_t)((((trie))->index)[(0)+((c)>>
UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&UTRIE2_DATA_MASK
))]
;
80 } else if(trie->data32!=NULL__null) {
81 return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c)((trie))->data32[(((int32_t)((((trie))->index)[(0)+((c)
>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&
UTRIE2_DATA_MASK))]
;
82 } else {
83 return get32(trie->newTrie, c, FALSE0);
84 }
85}
86
87static inline int32_t
88u8Index(const UTrie2 *trie, UChar32 c, int32_t i) {
89 int32_t idx=
90 _UTRIE2_INDEX_FROM_CP(((uint32_t)(c)<0xd800 ? (((int32_t)(((trie)->index)[(0)
+((c)>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ (
(c)&UTRIE2_DATA_MASK)) : (uint32_t)(c)<=0xffff ? (((int32_t
)(((trie)->index)[((c)<=0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2) : 0)+((c)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&UTRIE2_DATA_MASK)) :
(uint32_t)(c)>0x10ffff ? (trie->data32==__null ? trie->
indexLength : 0)+UTRIE2_BAD_UTF8_DATA_OFFSET : (c)>=(trie)
->highStart ? (trie)->highValueIndex : (((int32_t)(((trie
)->index)[ ((trie)->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ ((c)>>UTRIE2_SHIFT_1)]+ (((c)>>UTRIE2_SHIFT_2)
&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT)+ ((c)
&UTRIE2_DATA_MASK)))
91 trie,((uint32_t)(c)<0xd800 ? (((int32_t)(((trie)->index)[(0)
+((c)>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ (
(c)&UTRIE2_DATA_MASK)) : (uint32_t)(c)<=0xffff ? (((int32_t
)(((trie)->index)[((c)<=0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2) : 0)+((c)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&UTRIE2_DATA_MASK)) :
(uint32_t)(c)>0x10ffff ? (trie->data32==__null ? trie->
indexLength : 0)+UTRIE2_BAD_UTF8_DATA_OFFSET : (c)>=(trie)
->highStart ? (trie)->highValueIndex : (((int32_t)(((trie
)->index)[ ((trie)->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ ((c)>>UTRIE2_SHIFT_1)]+ (((c)>>UTRIE2_SHIFT_2)
&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT)+ ((c)
&UTRIE2_DATA_MASK)))
92 trie->data32==NULL ? trie->indexLength : 0,((uint32_t)(c)<0xd800 ? (((int32_t)(((trie)->index)[(0)
+((c)>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ (
(c)&UTRIE2_DATA_MASK)) : (uint32_t)(c)<=0xffff ? (((int32_t
)(((trie)->index)[((c)<=0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2) : 0)+((c)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&UTRIE2_DATA_MASK)) :
(uint32_t)(c)>0x10ffff ? (trie->data32==__null ? trie->
indexLength : 0)+UTRIE2_BAD_UTF8_DATA_OFFSET : (c)>=(trie)
->highStart ? (trie)->highValueIndex : (((int32_t)(((trie
)->index)[ ((trie)->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ ((c)>>UTRIE2_SHIFT_1)]+ (((c)>>UTRIE2_SHIFT_2)
&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT)+ ((c)
&UTRIE2_DATA_MASK)))
93 c)((uint32_t)(c)<0xd800 ? (((int32_t)(((trie)->index)[(0)
+((c)>>UTRIE2_SHIFT_2)]) <<UTRIE2_INDEX_SHIFT)+ (
(c)&UTRIE2_DATA_MASK)) : (uint32_t)(c)<=0xffff ? (((int32_t
)(((trie)->index)[((c)<=0xdbff ? UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2) : 0)+((c)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((c)&UTRIE2_DATA_MASK)) :
(uint32_t)(c)>0x10ffff ? (trie->data32==__null ? trie->
indexLength : 0)+UTRIE2_BAD_UTF8_DATA_OFFSET : (c)>=(trie)
->highStart ? (trie)->highValueIndex : (((int32_t)(((trie
)->index)[ ((trie)->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ ((c)>>UTRIE2_SHIFT_1)]+ (((c)>>UTRIE2_SHIFT_2)
&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT)+ ((c)
&UTRIE2_DATA_MASK)))
;
94 return (idx<<3)|i;
95}
96
97U_CAPIextern "C" int32_t U_EXPORT2
98utrie2_internalU8NextIndexutrie2_internalU8NextIndex_71(const UTrie2 *trie, UChar32 c,
99 const uint8_t *src, const uint8_t *limit) {
100 int32_t i, length;
101 i=0;
102 /* support 64-bit pointers by avoiding cast of arbitrary difference */
103 if((limit-src)<=7) {
104 length=(int32_t)(limit-src);
105 } else {
106 length=7;
107 }
108 c=utf8_nextCharSafeBodyutf8_nextCharSafeBody_71(src, &i, length, c, -1);
109 return u8Index(trie, c, i);
110}
111
112U_CAPIextern "C" int32_t U_EXPORT2
113utrie2_internalU8PrevIndexutrie2_internalU8PrevIndex_71(const UTrie2 *trie, UChar32 c,
114 const uint8_t *start, const uint8_t *src) {
115 int32_t i, length;
116 /* support 64-bit pointers by avoiding cast of arbitrary difference */
117 if((src-start)<=7) {
118 i=length=(int32_t)(src-start);
119 } else {
120 i=length=7;
121 start=src-7;
122 }
123 c=utf8_prevCharSafeBodyutf8_prevCharSafeBody_71(start, 0, &i, c, -1);
124 i=length-i; /* number of bytes read backward from src */
125 return u8Index(trie, c, i);
126}
127
128U_CAPIextern "C" UTrie2 * U_EXPORT2
129utrie2_openFromSerializedutrie2_openFromSerialized_71(UTrie2ValueBits valueBits,
130 const void *data, int32_t length, int32_t *pActualLength,
131 UErrorCode *pErrorCode) {
132 const UTrie2Header *header;
133 const uint16_t *p16;
134 int32_t actualLength;
135
136 UTrie2 tempTrie;
137 UTrie2 *trie;
138
139 if(U_FAILURE(*pErrorCode)) {
140 return 0;
141 }
142
143 if( length<=0 || (U_POINTER_MASK_LSB(data, 3)((uintptr_t)(data) & (3))!=0) ||
144 valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits
145 ) {
146 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
147 return 0;
148 }
149
150 /* enough data for a trie header? */
151 if(length<(int32_t)sizeof(UTrie2Header)) {
152 *pErrorCode=U_INVALID_FORMAT_ERROR;
153 return 0;
154 }
155
156 /* check the signature */
157 header=(const UTrie2Header *)data;
158 if(header->signature!=UTRIE2_SIG0x54726932) {
159 *pErrorCode=U_INVALID_FORMAT_ERROR;
160 return 0;
161 }
162
163 /* get the options */
164 if(valueBits!=(UTrie2ValueBits)(header->options&UTRIE2_OPTIONS_VALUE_BITS_MASK)) {
165 *pErrorCode=U_INVALID_FORMAT_ERROR;
166 return 0;
167 }
168
169 /* get the length values and offsets */
170 uprv_memset(&tempTrie, 0, sizeof(tempTrie)):: memset(&tempTrie, 0, sizeof(tempTrie));
171 tempTrie.indexLength=header->indexLength;
172 tempTrie.dataLength=header->shiftedDataLength<<UTRIE2_INDEX_SHIFT;
173 tempTrie.index2NullOffset=header->index2NullOffset;
174 tempTrie.dataNullOffset=header->dataNullOffset;
175
176 tempTrie.highStart=header->shiftedHighStart<<UTRIE2_SHIFT_1;
177 tempTrie.highValueIndex=tempTrie.dataLength-UTRIE2_DATA_GRANULARITY;
178 if(valueBits==UTRIE2_16_VALUE_BITS) {
179 tempTrie.highValueIndex+=tempTrie.indexLength;
180 }
181
182 /* calculate the actual length */
183 actualLength=(int32_t)sizeof(UTrie2Header)+tempTrie.indexLength*2;
184 if(valueBits==UTRIE2_16_VALUE_BITS) {
185 actualLength+=tempTrie.dataLength*2;
186 } else {
187 actualLength+=tempTrie.dataLength*4;
188 }
189 if(length<actualLength) {
190 *pErrorCode=U_INVALID_FORMAT_ERROR; /* not enough bytes */
191 return 0;
192 }
193
194 /* allocate the trie */
195 trie=(UTrie2 *)uprv_mallocuprv_malloc_71(sizeof(UTrie2));
196 if(trie==NULL__null) {
197 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
198 return 0;
199 }
200 uprv_memcpy(trie, &tempTrie, sizeof(tempTrie))do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(trie, &
tempTrie, sizeof(tempTrie)); } while (false)
;
201 trie->memory=(uint32_t *)data;
202 trie->length=actualLength;
203 trie->isMemoryOwned=FALSE0;
204#ifdef UTRIE2_DEBUG
205 trie->name="fromSerialized";
206#endif
207
208 /* set the pointers to its index and data arrays */
209 p16=(const uint16_t *)(header+1);
210 trie->index=p16;
211 p16+=trie->indexLength;
212
213 /* get the data */
214 switch(valueBits) {
215 case UTRIE2_16_VALUE_BITS:
216 trie->data16=p16;
217 trie->data32=NULL__null;
218 trie->initialValue=trie->index[trie->dataNullOffset];
219 trie->errorValue=trie->data16[UTRIE2_BAD_UTF8_DATA_OFFSET];
220 break;
221 case UTRIE2_32_VALUE_BITS:
222 trie->data16=NULL__null;
223 trie->data32=(const uint32_t *)p16;
224 trie->initialValue=trie->data32[trie->dataNullOffset];
225 trie->errorValue=trie->data32[UTRIE2_BAD_UTF8_DATA_OFFSET];
226 break;
227 default:
228 *pErrorCode=U_INVALID_FORMAT_ERROR;
229 return 0;
230 }
231
232 if(pActualLength!=NULL__null) {
233 *pActualLength=actualLength;
234 }
235 return trie;
236}
237
238U_CAPIextern "C" UTrie2 * U_EXPORT2
239utrie2_openDummyutrie2_openDummy_71(UTrie2ValueBits valueBits,
240 uint32_t initialValue, uint32_t errorValue,
241 UErrorCode *pErrorCode) {
242 UTrie2 *trie;
243 UTrie2Header *header;
244 uint32_t *p;
245 uint16_t *dest16;
246 int32_t indexLength, dataLength, length, i;
247 int32_t dataMove; /* >0 if the data is moved to the end of the index array */
248
249 if(U_FAILURE(*pErrorCode)) {
250 return 0;
251 }
252
253 if(valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits) {
254 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
255 return 0;
256 }
257
258 /* calculate the total length of the dummy trie data */
259 indexLength=UTRIE2_INDEX_1_OFFSET;
260 dataLength=UTRIE2_DATA_START_OFFSET+UTRIE2_DATA_GRANULARITY;
261 length=(int32_t)sizeof(UTrie2Header)+indexLength*2;
262 if(valueBits==UTRIE2_16_VALUE_BITS) {
263 length+=dataLength*2;
264 } else {
265 length+=dataLength*4;
266 }
267
268 /* allocate the trie */
269 trie=(UTrie2 *)uprv_mallocuprv_malloc_71(sizeof(UTrie2));
270 if(trie==NULL__null) {
271 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
272 return 0;
273 }
274 uprv_memset(trie, 0, sizeof(UTrie2)):: memset(trie, 0, sizeof(UTrie2));
275 trie->memory=uprv_mallocuprv_malloc_71(length);
276 if(trie->memory==NULL__null) {
277 uprv_freeuprv_free_71(trie);
278 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
279 return 0;
280 }
281 trie->length=length;
282 trie->isMemoryOwned=TRUE1;
283
284 /* set the UTrie2 fields */
285 if(valueBits==UTRIE2_16_VALUE_BITS) {
286 dataMove=indexLength;
287 } else {
288 dataMove=0;
289 }
290
291 trie->indexLength=indexLength;
292 trie->dataLength=dataLength;
293 trie->index2NullOffset=UTRIE2_INDEX_2_OFFSET;
294 trie->dataNullOffset=(uint16_t)dataMove;
295 trie->initialValue=initialValue;
296 trie->errorValue=errorValue;
297 trie->highStart=0;
298 trie->highValueIndex=dataMove+UTRIE2_DATA_START_OFFSET;
299#ifdef UTRIE2_DEBUG
300 trie->name="dummy";
301#endif
302
303 /* set the header fields */
304 header=(UTrie2Header *)trie->memory;
305
306 header->signature=UTRIE2_SIG0x54726932; /* "Tri2" */
307 header->options=(uint16_t)valueBits;
308
309 header->indexLength=(uint16_t)indexLength;
310 header->shiftedDataLength=(uint16_t)(dataLength>>UTRIE2_INDEX_SHIFT);
311 header->index2NullOffset=(uint16_t)UTRIE2_INDEX_2_OFFSET;
312 header->dataNullOffset=(uint16_t)dataMove;
313 header->shiftedHighStart=0;
314
315 /* fill the index and data arrays */
316 dest16=(uint16_t *)(header+1);
317 trie->index=dest16;
318
319 /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT */
320 for(i=0; i<UTRIE2_INDEX_2_BMP_LENGTH; ++i) {
321 *dest16++=(uint16_t)(dataMove>>UTRIE2_INDEX_SHIFT); /* null data block */
322 }
323
324 /* write UTF-8 2-byte index-2 values, not right-shifted */
325 for(i=0; i<(0xc2-0xc0); ++i) { /* C0..C1 */
326 *dest16++=(uint16_t)(dataMove+UTRIE2_BAD_UTF8_DATA_OFFSET);
327 }
328 for(; i<(0xe0-0xc0); ++i) { /* C2..DF */
329 *dest16++=(uint16_t)dataMove;
330 }
331
332 /* write the 16/32-bit data array */
333 switch(valueBits) {
334 case UTRIE2_16_VALUE_BITS:
335 /* write 16-bit data values */
336 trie->data16=dest16;
337 trie->data32=NULL__null;
338 for(i=0; i<0x80; ++i) {
339 *dest16++=(uint16_t)initialValue;
340 }
341 for(; i<0xc0; ++i) {
342 *dest16++=(uint16_t)errorValue;
343 }
344 /* highValue and reserved values */
345 for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
346 *dest16++=(uint16_t)initialValue;
347 }
348 break;
349 case UTRIE2_32_VALUE_BITS:
350 /* write 32-bit data values */
351 p=(uint32_t *)dest16;
352 trie->data16=NULL__null;
353 trie->data32=p;
354 for(i=0; i<0x80; ++i) {
355 *p++=initialValue;
356 }
357 for(; i<0xc0; ++i) {
358 *p++=errorValue;
359 }
360 /* highValue and reserved values */
361 for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
362 *p++=initialValue;
363 }
364 break;
365 default:
366 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
367 return 0;
368 }
369
370 return trie;
371}
372
373U_CAPIextern "C" void U_EXPORT2
374utrie2_closeutrie2_close_71(UTrie2 *trie) {
375 if(trie!=NULL__null) {
376 if(trie->isMemoryOwned) {
377 uprv_freeuprv_free_71(trie->memory);
378 }
379 if(trie->newTrie!=NULL__null) {
380 uprv_freeuprv_free_71(trie->newTrie->data);
381#ifdef UCPTRIE_DEBUG
382 umutablecptrie_closeumutablecptrie_close_71(trie->newTrie->t3);
383#endif
384 uprv_freeuprv_free_71(trie->newTrie);
385 }
386 uprv_freeuprv_free_71(trie);
387 }
388}
389
390U_CAPIextern "C" UBool U_EXPORT2
391utrie2_isFrozenutrie2_isFrozen_71(const UTrie2 *trie) {
392 return (UBool)(trie->newTrie==NULL__null);
393}
394
395U_CAPIextern "C" int32_t U_EXPORT2
396utrie2_serializeutrie2_serialize_71(const UTrie2 *trie,
397 void *data, int32_t capacity,
398 UErrorCode *pErrorCode) {
399 /* argument check */
400 if(U_FAILURE(*pErrorCode)) {
401 return 0;
402 }
403
404 if( trie==NULL__null || trie->memory==NULL__null || trie->newTrie!=NULL__null ||
405 capacity<0 || (capacity>0 && (data==NULL__null || (U_POINTER_MASK_LSB(data, 3)((uintptr_t)(data) & (3))!=0)))
406 ) {
407 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
408 return 0;
409 }
410
411 if(capacity>=trie->length) {
412 uprv_memcpy(data, trie->memory, trie->length)do { clang diagnostic push clang diagnostic ignored "-Waddress"
(void)0; (void)0; clang diagnostic pop :: memcpy(data, trie
->memory, trie->length); } while (false)
;
413 } else {
414 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
415 }
416 return trie->length;
417}
418
419/* enumeration -------------------------------------------------------------- */
420
421#define MIN_VALUE(a, b)((a)<(b) ? (a) : (b)) ((a)<(b) ? (a) : (b))
422
423/* default UTrie2EnumValue() returns the input value itself */
424static uint32_t U_CALLCONV
425enumSameValue(const void * /*context*/, uint32_t value) {
426 return value;
427}
428
429/**
430 * Enumerate all ranges of code points with the same relevant values.
431 * The values are transformed from the raw trie entries by the enumValue function.
432 *
433 * Currently requires start<limit and both start and limit must be multiples
434 * of UTRIE2_DATA_BLOCK_LENGTH.
435 *
436 * Optimizations:
437 * - Skip a whole block if we know that it is filled with a single value,
438 * and it is the same as we visited just before.
439 * - Handle the null block specially because we know a priori that it is filled
440 * with a single value.
441 */
442static void
443enumEitherTrie(const UTrie2 *trie,
444 UChar32 start, UChar32 limit,
445 UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
446 const uint32_t *data32;
447 const uint16_t *idx;
448
449 uint32_t value, prevValue, initialValue;
450 UChar32 c, prev, highStart;
451 int32_t j, i2Block, prevI2Block, index2NullOffset, block, prevBlock, nullBlock;
452
453 if(enumRange==NULL__null) {
4
Assuming 'enumRange' is not equal to NULL
5
Taking false branch
454 return;
455 }
456 if(enumValue==NULL__null) {
6
Assuming 'enumValue' is not equal to NULL
7
Taking false branch
457 enumValue=enumSameValue;
458 }
459
460 if(trie->newTrie==NULL__null) {
8
Assuming field 'newTrie' is not equal to NULL
9
Taking false branch
461 /* frozen trie */
462 idx=trie->index;
463 U_ASSERT(idx!=NULL)(void)0; /* the following code assumes trie->newTrie is not NULL when idx is NULL */
464 data32=trie->data32;
465
466 index2NullOffset=trie->index2NullOffset;
467 nullBlock=trie->dataNullOffset;
468 } else {
469 /* unfrozen, mutable trie */
470 idx=NULL__null;
10
Null pointer value stored to 'idx'
471 data32=trie->newTrie->data;
472 U_ASSERT(data32!=NULL)(void)0; /* the following code assumes idx is not NULL when data32 is NULL */
473
474 index2NullOffset=trie->newTrie->index2NullOffset;
475 nullBlock=trie->newTrie->dataNullOffset;
476 }
477
478 highStart=trie->highStart;
479
480 /* get the enumeration value that corresponds to an initial-value trie data entry */
481 initialValue=enumValue(context, trie->initialValue);
482
483 /* set variables for previous range */
484 prevI2Block=-1;
485 prevBlock=-1;
486 prev=start;
487 prevValue=0;
488
489 /* enumerate index-2 blocks */
490 for(c=start; c<limit && c<highStart;) {
11
Assuming 'c' is < 'limit'
12
Assuming 'c' is < 'highStart'
13
Loop condition is true. Entering loop body
491 /* Code point limit for iterating inside this i2Block. */
492 UChar32 tempLimit=c+UTRIE2_CP_PER_INDEX_1_ENTRY;
493 if(limit<tempLimit) {
14
Assuming 'limit' is >= 'tempLimit'
15
Taking false branch
494 tempLimit=limit;
495 }
496 if(c<=0xffff) {
16
Assuming 'c' is <= 65535
17
Taking true branch
497 if(!U_IS_SURROGATE(c)(((c)&0xfffff800)==0xd800)) {
18
Assuming the condition is false
19
Taking true branch
498 i2Block=c>>UTRIE2_SHIFT_2;
499 } else if(U_IS_SURROGATE_LEAD(c)(((c)&0x400)==0)) {
500 /*
501 * Enumerate values for lead surrogate code points, not code units:
502 * This special block has half the normal length.
503 */
504 i2Block=UTRIE2_LSCP_INDEX_2_OFFSET;
505 tempLimit=MIN_VALUE(0xdc00, limit)((0xdc00)<(limit) ? (0xdc00) : (limit));
506 } else {
507 /*
508 * Switch back to the normal part of the index-2 table.
509 * Enumerate the second half of the surrogates block.
510 */
511 i2Block=0xd800>>UTRIE2_SHIFT_2;
512 tempLimit=MIN_VALUE(0xe000, limit)((0xe000)<(limit) ? (0xe000) : (limit));
513 }
514 } else {
515 /* supplementary code points */
516 if(idx!=NULL__null) {
517 i2Block=idx[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+
518 (c>>UTRIE2_SHIFT_1)];
519 } else {
520 i2Block=trie->newTrie->index1[c>>UTRIE2_SHIFT_1];
521 }
522 if(i2Block==prevI2Block && (c-prev)>=UTRIE2_CP_PER_INDEX_1_ENTRY) {
523 /*
524 * The index-2 block is the same as the previous one, and filled with prevValue.
525 * Only possible for supplementary code points because the linear-BMP index-2
526 * table creates unique i2Block values.
527 */
528 c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
529 continue;
530 }
531 }
532 prevI2Block=i2Block;
533 if(i2Block==index2NullOffset) {
20
Assuming 'i2Block' is not equal to 'index2NullOffset'
21
Taking false branch
534 /* this is the null index-2 block */
535 if(prevValue!=initialValue) {
536 if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
537 return;
538 }
539 prevBlock=nullBlock;
540 prev=c;
541 prevValue=initialValue;
542 }
543 c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
544 } else {
545 /* enumerate data blocks for one index-2 block */
546 int32_t i2, i2Limit;
547 i2=(c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
548 if((c>>UTRIE2_SHIFT_1)==(tempLimit>>UTRIE2_SHIFT_1)) {
22
Assuming the condition is false
23
Taking false branch
549 i2Limit=(tempLimit>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
550 } else {
551 i2Limit=UTRIE2_INDEX_2_BLOCK_LENGTH;
552 }
553 for(; i2<i2Limit; ++i2) {
24
Assuming 'i2' is < 'i2Limit'
25
Loop condition is true. Entering loop body
554 if(idx
25.1
'idx' is equal to NULL
!=NULL__null) {
26
Taking false branch
555 block=(int32_t)idx[i2Block+i2]<<UTRIE2_INDEX_SHIFT;
556 } else {
557 block=trie->newTrie->index2[i2Block+i2];
558 }
559 if(block==prevBlock && (c-prev)>=UTRIE2_DATA_BLOCK_LENGTH) {
27
Assuming 'block' is not equal to 'prevBlock'
560 /* the block is the same as the previous one, and filled with prevValue */
561 c+=UTRIE2_DATA_BLOCK_LENGTH;
562 continue;
563 }
564 prevBlock=block;
565 if(block==nullBlock) {
28
Assuming 'block' is not equal to 'nullBlock'
29
Taking false branch
566 /* this is the null data block */
567 if(prevValue!=initialValue) {
568 if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
569 return;
570 }
571 prev=c;
572 prevValue=initialValue;
573 }
574 c+=UTRIE2_DATA_BLOCK_LENGTH;
575 } else {
576 for(j=0; j<UTRIE2_DATA_BLOCK_LENGTH; ++j) {
30
Loop condition is true. Entering loop body
577 value=enumValue(context, data32!=NULL__null ? data32[block+j] : idx[block+j]);
31
Assuming 'data32' is equal to NULL
32
'?' condition is false
33
Array access (from variable 'idx') results in a null pointer dereference
578 if(value!=prevValue) {
579 if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
580 return;
581 }
582 prev=c;
583 prevValue=value;
584 }
585 ++c;
586 }
587 }
588 }
589 }
590 }
591
592 if(c>limit) {
593 c=limit; /* could be higher if in the index2NullOffset */
594 } else if(c<limit) {
595 /* c==highStart<limit */
596 uint32_t highValue;
597 if(idx!=NULL__null) {
598 highValue=
599 data32!=NULL__null ?
600 data32[trie->highValueIndex] :
601 idx[trie->highValueIndex];
602 } else {
603 highValue=trie->newTrie->data[trie->newTrie->dataLength-UTRIE2_DATA_GRANULARITY];
604 }
605 value=enumValue(context, highValue);
606 if(value!=prevValue) {
607 if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
608 return;
609 }
610 prev=c;
611 prevValue=value;
612 }
613 c=limit;
614 }
615
616 /* deliver last range */
617 enumRange(context, prev, c-1, prevValue);
618}
619
620U_CAPIextern "C" void U_EXPORT2
621utrie2_enumutrie2_enum_71(const UTrie2 *trie,
622 UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
623 enumEitherTrie(trie, 0, 0x110000, enumValue, enumRange, context);
624}
625
626U_CAPIextern "C" void U_EXPORT2
627utrie2_enumForLeadSurrogateutrie2_enumForLeadSurrogate_71(const UTrie2 *trie, UChar32 lead,
628 UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange,
629 const void *context) {
630 if(!U16_IS_LEAD(lead)(((lead)&0xfffffc00)==0xd800)) {
1
Assuming the condition is true
2
Taking false branch
631 return;
632 }
633 lead=(lead-0xd7c0)<<10; /* start code point */
634 enumEitherTrie(trie, lead, lead+0x400, enumValue, enumRange, context);
3
Calling 'enumEitherTrie'
635}
636
637/* C++ convenience wrappers ------------------------------------------------- */
638
639U_NAMESPACE_BEGINnamespace icu_71 {
640
641uint16_t BackwardUTrie2StringIterator::previous16() {
642 codePointLimit=codePointStart;
643 if(start>=codePointStart) {
644 codePoint=U_SENTINEL(-1);
645 return static_cast<uint16_t>(trie->errorValue);
646 }
647 uint16_t result;
648 UTRIE2_U16_PREV16(trie, start, codePointStart, codePoint, result)do { { uint16_t __c2; (codePoint)=*--(codePointStart); if(!((
(codePoint)&0xfffffc00)==0xdc00) || (codePointStart)==(start
) || !(((__c2=*((codePointStart)-1))&0xfffffc00)==0xd800)
) { (result)=(trie)->index[(((int32_t)(((trie)->index)[
((((codePoint)&0xfffffc00)==0xd800) ? UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2) : 0)+((codePoint)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((codePoint)&UTRIE2_DATA_MASK
))]; } else { --(codePointStart); (codePoint)=(((UChar32)(__c2
)<<10UL)+(UChar32)((codePoint))-((0xd800<<10UL)+0xdc00
-0x10000)); (result)=((trie))->index[((codePoint))>=((trie
))->highStart ? ((trie))->highValueIndex : (((int32_t)(
(((trie))->index)[ (((trie))->index)[(UTRIE2_INDEX_1_OFFSET
-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+ (((codePoint))>>UTRIE2_SHIFT_1
)]+ ((((codePoint))>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK
)]) <<UTRIE2_INDEX_SHIFT)+ (((codePoint))&UTRIE2_DATA_MASK
))]; } } } while (false)
;
649 return result;
650}
651
652uint16_t ForwardUTrie2StringIterator::next16() {
653 codePointStart=codePointLimit;
654 if(codePointLimit==limit) {
655 codePoint=U_SENTINEL(-1);
656 return static_cast<uint16_t>(trie->errorValue);
657 }
658 uint16_t result;
659 UTRIE2_U16_NEXT16(trie, codePointLimit, limit, codePoint, result)do { { uint16_t __c2; (codePoint)=*(codePointLimit)++; if(!((
(codePoint)&0xfffffc00)==0xd800)) { (result)=(trie)->index
[(((int32_t)(((trie)->index)[(0)+((codePoint)>>UTRIE2_SHIFT_2
)]) <<UTRIE2_INDEX_SHIFT)+ ((codePoint)&UTRIE2_DATA_MASK
))]; } else if((codePointLimit)==(limit) || !(((__c2=*(codePointLimit
))&0xfffffc00)==0xdc00)) { (result)=(trie)->index[(((int32_t
)(((trie)->index)[(UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>
UTRIE2_SHIFT_2))+((codePoint)>>UTRIE2_SHIFT_2)]) <<
UTRIE2_INDEX_SHIFT)+ ((codePoint)&UTRIE2_DATA_MASK))]; } else
{ ++(codePointLimit); (codePoint)=(((UChar32)((codePoint))<<
10UL)+(UChar32)(__c2)-((0xd800<<10UL)+0xdc00-0x10000));
(result)=((trie))->index[((codePoint))>=((trie))->highStart
? ((trie))->highValueIndex : (((int32_t)((((trie))->index
)[ (((trie))->index)[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+ (((codePoint))>>UTRIE2_SHIFT_1)]+ ((((codePoint))>>
UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK)]) <<UTRIE2_INDEX_SHIFT
)+ (((codePoint))&UTRIE2_DATA_MASK))]; } } } while (false
)
;
660 return result;
661}
662
663U_NAMESPACE_END}