/src/libgit2/deps/pcre2/pcre2_xclass.c
Line | Count | Source |
1 | | /************************************************* |
2 | | * Perl-Compatible Regular Expressions * |
3 | | *************************************************/ |
4 | | |
5 | | /* PCRE is a library of functions to support regular expressions whose syntax |
6 | | and semantics are as close as possible to those of the Perl 5 language. |
7 | | |
8 | | Written by Philip Hazel |
9 | | Original API code Copyright (c) 1997-2012 University of Cambridge |
10 | | New API code Copyright (c) 2016-2024 University of Cambridge |
11 | | |
12 | | ----------------------------------------------------------------------------- |
13 | | Redistribution and use in source and binary forms, with or without |
14 | | modification, are permitted provided that the following conditions are met: |
15 | | |
16 | | * Redistributions of source code must retain the above copyright notice, |
17 | | this list of conditions and the following disclaimer. |
18 | | |
19 | | * Redistributions in binary form must reproduce the above copyright |
20 | | notice, this list of conditions and the following disclaimer in the |
21 | | documentation and/or other materials provided with the distribution. |
22 | | |
23 | | * Neither the name of the University of Cambridge nor the names of its |
24 | | contributors may be used to endorse or promote products derived from |
25 | | this software without specific prior written permission. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
28 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
29 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
30 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
31 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
33 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
34 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
35 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
36 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
37 | | POSSIBILITY OF SUCH DAMAGE. |
38 | | ----------------------------------------------------------------------------- |
39 | | */ |
40 | | |
41 | | |
42 | | /* This module contains two internal functions that are used to match |
43 | | OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both |
44 | | pcre2_match() and pcre2_dfa_match(). */ |
45 | | |
46 | | |
47 | | #include "pcre2_internal.h" |
48 | | |
49 | | |
50 | | |
51 | | /************************************************* |
52 | | * Match character against an XCLASS * |
53 | | *************************************************/ |
54 | | |
55 | | /* This function is called to match a character against an extended class that |
56 | | might contain codepoints above 255 and/or Unicode properties. |
57 | | |
58 | | Arguments: |
59 | | c the character |
60 | | data points to the flag code unit of the XCLASS data |
61 | | utf TRUE if in UTF mode |
62 | | |
63 | | Returns: TRUE if character matches, else FALSE |
64 | | */ |
65 | | |
66 | | BOOL |
67 | | PRIV(xclass)(uint32_t c, PCRE2_SPTR data, const uint8_t *char_lists_end, BOOL utf) |
68 | 53.2k | { |
69 | | /* Update PRIV(update_classbits) when this function is changed. */ |
70 | 53.2k | PCRE2_UCHAR t; |
71 | 53.2k | BOOL not_negated = (*data & XCL_NOT) == 0; |
72 | 53.2k | uint32_t type, max_index, min_index, value; |
73 | 53.2k | const uint8_t *next_char; |
74 | | |
75 | 53.2k | #if PCRE2_CODE_UNIT_WIDTH == 8 |
76 | | /* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ |
77 | 53.2k | utf = TRUE; |
78 | 53.2k | #endif |
79 | | |
80 | | /* Code points < 256 are matched against a bitmap, if one is present. */ |
81 | | |
82 | 53.2k | if ((*data++ & XCL_MAP) != 0) |
83 | 11.1k | { |
84 | 11.1k | if (c < 256) |
85 | 862 | return (((const uint8_t *)data)[c/8] & (1u << (c&7))) != 0; |
86 | | /* Skip bitmap. */ |
87 | 10.3k | data += 32 / sizeof(PCRE2_UCHAR); |
88 | 10.3k | } |
89 | | |
90 | | /* Match against the list of Unicode properties. We won't ever |
91 | | encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */ |
92 | 52.4k | #ifdef SUPPORT_UNICODE |
93 | 52.4k | if (*data == XCL_PROP || *data == XCL_NOTPROP) |
94 | 42.1k | { |
95 | | /* The UCD record is the same for all properties. */ |
96 | 42.1k | const ucd_record *prop = GET_UCD(c); |
97 | | |
98 | 42.1k | do |
99 | 44.3k | { |
100 | 44.3k | int chartype; |
101 | 44.3k | BOOL isprop = (*data++) == XCL_PROP; |
102 | 44.3k | BOOL ok; |
103 | | |
104 | 44.3k | switch(*data) |
105 | 44.3k | { |
106 | 3.47k | case PT_LAMP: |
107 | 3.47k | chartype = prop->chartype; |
108 | 3.47k | if ((chartype == ucp_Lu || chartype == ucp_Ll || |
109 | 1.30k | chartype == ucp_Lt) == isprop) return not_negated; |
110 | 2.76k | break; |
111 | | |
112 | 6.71k | case PT_GC: |
113 | 6.71k | if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop) |
114 | 2.99k | return not_negated; |
115 | 3.72k | break; |
116 | | |
117 | 3.72k | case PT_PC: |
118 | 1.02k | if ((data[1] == prop->chartype) == isprop) return not_negated; |
119 | 524 | break; |
120 | | |
121 | 524 | case PT_SC: |
122 | 514 | if ((data[1] == prop->script) == isprop) return not_negated; |
123 | 238 | break; |
124 | | |
125 | 1.45k | case PT_SCX: |
126 | 1.45k | ok = (data[1] == prop->script || |
127 | 633 | MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0); |
128 | 1.45k | if (ok == isprop) return not_negated; |
129 | 634 | break; |
130 | | |
131 | 1.03k | case PT_ALNUM: |
132 | 1.03k | chartype = prop->chartype; |
133 | 1.03k | if ((PRIV(ucp_gentype)[chartype] == ucp_L || |
134 | 529 | PRIV(ucp_gentype)[chartype] == ucp_N) == isprop) |
135 | 610 | return not_negated; |
136 | 427 | break; |
137 | | |
138 | | /* Perl space used to exclude VT, but from Perl 5.18 it is included, |
139 | | which means that Perl space and POSIX space are now identical. PCRE |
140 | | was changed at release 8.34. */ |
141 | | |
142 | 8.80k | case PT_SPACE: /* Perl space */ |
143 | 11.9k | case PT_PXSPACE: /* POSIX space */ |
144 | 11.9k | switch(c) |
145 | 11.9k | { |
146 | 64.5k | HSPACE_CASES: |
147 | 64.5k | VSPACE_CASES: |
148 | 53.9k | if (isprop) return not_negated; |
149 | 5.34k | break; |
150 | | |
151 | 5.34k | default: |
152 | 2.51k | if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop) |
153 | 803 | return not_negated; |
154 | 1.71k | break; |
155 | 11.9k | } |
156 | 7.05k | break; |
157 | | |
158 | 7.05k | case PT_WORD: |
159 | 2.85k | chartype = prop->chartype; |
160 | 2.85k | if ((PRIV(ucp_gentype)[chartype] == ucp_L || |
161 | 1.24k | PRIV(ucp_gentype)[chartype] == ucp_N || |
162 | 910 | chartype == ucp_Mn || chartype == ucp_Pc) == isprop) |
163 | 1.09k | return not_negated; |
164 | 1.76k | break; |
165 | | |
166 | 3.95k | case PT_UCNC: |
167 | 3.95k | if (c < 0xa0) |
168 | 2.35k | { |
169 | 2.35k | if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT || |
170 | 1.35k | c == CHAR_GRAVE_ACCENT) == isprop) |
171 | 1.11k | return not_negated; |
172 | 2.35k | } |
173 | 1.59k | else |
174 | 1.59k | { |
175 | 1.59k | if ((c < 0xd800 || c > 0xdfff) == isprop) |
176 | 814 | return not_negated; |
177 | 1.59k | } |
178 | 2.02k | break; |
179 | | |
180 | 2.02k | case PT_BIDICL: |
181 | 495 | if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop) |
182 | 292 | return not_negated; |
183 | 203 | break; |
184 | | |
185 | 540 | case PT_BOOL: |
186 | 540 | ok = MAPBIT(PRIV(ucd_boolprop_sets) + |
187 | 540 | UCD_BPROPS_PROP(prop), data[1]) != 0; |
188 | 540 | if (ok == isprop) return not_negated; |
189 | 273 | break; |
190 | | |
191 | | /* The following three properties can occur only in an XCLASS, as there |
192 | | is no \p or \P coding for them. */ |
193 | | |
194 | | /* Graphic character. Implement this as not Z (space or separator) and |
195 | | not C (other), except for Cf (format) with a few exceptions. This seems |
196 | | to be what Perl does. The exceptional characters are: |
197 | | |
198 | | U+061C Arabic Letter Mark |
199 | | U+180E Mongolian Vowel Separator |
200 | | U+2066 - U+2069 Various "isolate"s |
201 | | */ |
202 | | |
203 | 2.28k | case PT_PXGRAPH: |
204 | 2.28k | chartype = prop->chartype; |
205 | 2.28k | if ((PRIV(ucp_gentype)[chartype] != ucp_Z && |
206 | 2.02k | (PRIV(ucp_gentype)[chartype] != ucp_C || |
207 | 1.71k | (chartype == ucp_Cf && |
208 | 1.22k | c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069)) |
209 | 2.02k | )) == isprop) |
210 | 1.17k | return not_negated; |
211 | 1.10k | break; |
212 | | |
213 | | /* Printable character: same as graphic, with the addition of Zs, i.e. |
214 | | not Zl and not Zp, and U+180E. */ |
215 | | |
216 | 1.69k | case PT_PXPRINT: |
217 | 1.69k | chartype = prop->chartype; |
218 | 1.69k | if ((chartype != ucp_Zl && |
219 | 1.40k | chartype != ucp_Zp && |
220 | 1.07k | (PRIV(ucp_gentype)[chartype] != ucp_C || |
221 | 781 | (chartype == ucp_Cf && |
222 | 482 | c != 0x061c && (c < 0x2066 || c > 0x2069)) |
223 | 1.07k | )) == isprop) |
224 | 529 | return not_negated; |
225 | 1.16k | break; |
226 | | |
227 | | /* Punctuation: all Unicode punctuation, plus ASCII characters that |
228 | | Unicode treats as symbols rather than punctuation, for Perl |
229 | | compatibility (these are $+<=>^`|~). */ |
230 | | |
231 | 1.16k | case PT_PXPUNCT: |
232 | 956 | chartype = prop->chartype; |
233 | 956 | if ((PRIV(ucp_gentype)[chartype] == ucp_P || |
234 | 707 | (c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop) |
235 | 592 | return not_negated; |
236 | 364 | break; |
237 | | |
238 | | /* Perl has two sets of hex digits */ |
239 | | |
240 | 5.44k | case PT_PXXDIGIT: |
241 | 5.44k | if (((c >= CHAR_0 && c <= CHAR_9) || |
242 | 5.14k | (c >= CHAR_A && c <= CHAR_F) || |
243 | 4.78k | (c >= CHAR_a && c <= CHAR_f) || |
244 | 4.38k | (c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */ |
245 | 3.83k | (c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */ |
246 | 3.63k | (c >= 0xff41 && c <= 0xff46)) == isprop) |
247 | 1.81k | return not_negated; |
248 | 3.63k | break; |
249 | | |
250 | | /* This should never occur, but compilers may mutter if there is no |
251 | | default. */ |
252 | | |
253 | | /* LCOV_EXCL_START */ |
254 | 3.63k | default: |
255 | 0 | PCRE2_DEBUG_UNREACHABLE(); |
256 | 0 | return FALSE; |
257 | | /* LCOV_EXCL_STOP */ |
258 | 44.3k | } |
259 | | |
260 | 25.8k | data += 2; |
261 | 25.8k | } |
262 | 42.1k | while (*data == XCL_PROP || *data == XCL_NOTPROP); |
263 | 42.1k | } |
264 | | #else |
265 | | (void)utf; /* Avoid compiler warning */ |
266 | | #endif /* SUPPORT_UNICODE */ |
267 | | |
268 | | /* Match against large chars or ranges that end with a large char. */ |
269 | 33.9k | if (*data < XCL_LIST) |
270 | 26.2k | { |
271 | 26.7k | while ((t = *data++) != XCL_END) |
272 | 2.82k | { |
273 | 2.82k | uint32_t x, y; |
274 | | |
275 | 2.82k | #ifdef SUPPORT_UNICODE |
276 | 2.82k | if (utf) |
277 | 2.82k | { |
278 | 2.82k | GETCHARINC(x, data); /* macro generates multiple statements */ |
279 | 2.82k | } |
280 | 0 | else |
281 | 0 | #endif |
282 | 0 | x = *data++; |
283 | | |
284 | 2.82k | if (t == XCL_SINGLE) |
285 | 1.12k | { |
286 | | /* Since character ranges follow the properties, and they are |
287 | | sorted, early return is possible for all characters <= x. */ |
288 | 1.12k | if (c <= x) return (c == x) ? not_negated : !not_negated; |
289 | 343 | continue; |
290 | 1.12k | } |
291 | | |
292 | 1.69k | PCRE2_ASSERT(t == XCL_RANGE); |
293 | 1.69k | #ifdef SUPPORT_UNICODE |
294 | 1.69k | if (utf) |
295 | 1.69k | { |
296 | 1.69k | GETCHARINC(y, data); /* macro generates multiple statements */ |
297 | 1.69k | } |
298 | 0 | else |
299 | 0 | #endif |
300 | 0 | y = *data++; |
301 | | |
302 | | /* Since character ranges follow the properties, and they are |
303 | | sorted, early return is possible for all characters <= y. */ |
304 | 1.69k | if (c <= y) return (c >= x) ? not_negated : !not_negated; |
305 | 1.69k | } |
306 | | |
307 | 23.9k | return !not_negated; /* char did not match */ |
308 | 26.2k | } |
309 | | |
310 | 7.74k | #if PCRE2_CODE_UNIT_WIDTH == 8 |
311 | 7.74k | type = (uint32_t)(data[0] << 8) | data[1]; |
312 | 7.74k | data += 2; |
313 | | #else |
314 | | type = data[0]; |
315 | | data++; |
316 | | #endif /* CODE_UNIT_WIDTH */ |
317 | | |
318 | | /* Align characters. */ |
319 | 7.74k | next_char = char_lists_end - (GET(data, 0) << 1); |
320 | 7.74k | type &= XCL_TYPE_MASK; |
321 | | |
322 | | /* Alignment check. */ |
323 | 7.74k | PCRE2_ASSERT(((uintptr_t)next_char & 0x1) == 0); |
324 | | |
325 | 7.74k | if (c >= XCL_CHAR_LIST_HIGH_16_START) |
326 | 4.25k | { |
327 | 4.25k | max_index = type & XCL_ITEM_COUNT_MASK; |
328 | 4.25k | if (max_index == XCL_ITEM_COUNT_MASK) |
329 | 3.99k | { |
330 | 3.99k | max_index = *(const uint16_t*)next_char; |
331 | 3.99k | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
332 | 3.99k | next_char += 2; |
333 | 3.99k | } |
334 | | |
335 | 4.25k | next_char += max_index << 1; |
336 | 4.25k | type >>= XCL_TYPE_BIT_LEN; |
337 | 4.25k | } |
338 | | |
339 | 7.74k | if (c < XCL_CHAR_LIST_LOW_32_START) |
340 | 4.55k | { |
341 | 4.55k | max_index = type & XCL_ITEM_COUNT_MASK; |
342 | | |
343 | 4.55k | c = (uint16_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); |
344 | | |
345 | 4.55k | if (max_index == XCL_ITEM_COUNT_MASK) |
346 | 3.74k | { |
347 | 3.74k | max_index = *(const uint16_t*)next_char; |
348 | 3.74k | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
349 | 3.74k | next_char += 2; |
350 | 3.74k | } |
351 | | |
352 | 4.55k | if (max_index == 0 || c < *(const uint16_t*)next_char) |
353 | 2.27k | return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; |
354 | | |
355 | 2.28k | min_index = 0; |
356 | 2.28k | value = ((const uint16_t*)next_char)[--max_index]; |
357 | 2.28k | if (c >= value) |
358 | 1.02k | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
359 | | |
360 | 1.25k | max_index--; |
361 | | |
362 | | /* Binary search of a range. */ |
363 | 4.11k | while (TRUE) |
364 | 4.11k | { |
365 | 4.11k | uint32_t mid_index = (min_index + max_index) >> 1; |
366 | 4.11k | value = ((const uint16_t*)next_char)[mid_index]; |
367 | | |
368 | 4.11k | if (c < value) |
369 | 1.20k | max_index = mid_index - 1; |
370 | 2.91k | else if (((const uint16_t*)next_char)[mid_index + 1] <= c) |
371 | 1.65k | min_index = mid_index + 1; |
372 | 1.25k | else |
373 | 1.25k | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
374 | 4.11k | } |
375 | 1.25k | } |
376 | | |
377 | | /* Skip the 16 bit ranges. */ |
378 | 3.18k | max_index = type & XCL_ITEM_COUNT_MASK; |
379 | 3.18k | if (max_index == XCL_ITEM_COUNT_MASK) |
380 | 302 | { |
381 | 302 | max_index = *(const uint16_t*)next_char; |
382 | 302 | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
383 | 302 | next_char += 2; |
384 | 302 | } |
385 | | |
386 | 3.18k | next_char += (max_index << 1); |
387 | 3.18k | type >>= XCL_TYPE_BIT_LEN; |
388 | | |
389 | | /* Alignment check. */ |
390 | 3.18k | PCRE2_ASSERT(((uintptr_t)next_char & 0x3) == 0); |
391 | | |
392 | 3.18k | max_index = type & XCL_ITEM_COUNT_MASK; |
393 | | |
394 | | #if PCRE2_CODE_UNIT_WIDTH == 32 |
395 | | if (c >= XCL_CHAR_LIST_HIGH_32_START) |
396 | | { |
397 | | if (max_index == XCL_ITEM_COUNT_MASK) |
398 | | { |
399 | | max_index = *(const uint32_t*)next_char; |
400 | | PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK); |
401 | | next_char += 4; |
402 | | } |
403 | | |
404 | | next_char += max_index << 2; |
405 | | type >>= XCL_TYPE_BIT_LEN; |
406 | | max_index = type & XCL_ITEM_COUNT_MASK; |
407 | | } |
408 | | #endif |
409 | | |
410 | 3.18k | c = (uint32_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END); |
411 | | |
412 | 3.18k | if (max_index == XCL_ITEM_COUNT_MASK) |
413 | 906 | { |
414 | 906 | max_index = *(const uint32_t*)next_char; |
415 | 906 | next_char += 4; |
416 | 906 | } |
417 | | |
418 | 3.18k | if (max_index == 0 || c < *(const uint32_t*)next_char) |
419 | 821 | return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated; |
420 | | |
421 | 2.36k | min_index = 0; |
422 | 2.36k | value = ((const uint32_t*)next_char)[--max_index]; |
423 | 2.36k | if (c >= value) |
424 | 701 | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
425 | | |
426 | 1.66k | max_index--; |
427 | | |
428 | | /* Binary search of a range. */ |
429 | 3.24k | while (TRUE) |
430 | 3.24k | { |
431 | 3.24k | uint32_t mid_index = (min_index + max_index) >> 1; |
432 | 3.24k | value = ((const uint32_t*)next_char)[mid_index]; |
433 | | |
434 | 3.24k | if (c < value) |
435 | 826 | max_index = mid_index - 1; |
436 | 2.42k | else if (((const uint32_t*)next_char)[mid_index + 1] <= c) |
437 | 759 | min_index = mid_index + 1; |
438 | 1.66k | else |
439 | 1.66k | return (value == c || (value & XCL_CHAR_END) == 0) == not_negated; |
440 | 3.24k | } |
441 | 1.66k | } |
442 | | |
443 | | |
444 | | |
445 | | /************************************************* |
446 | | * Match character against an ECLASS * |
447 | | *************************************************/ |
448 | | |
449 | | /* This function is called to match a character against an extended class |
450 | | used for describing characters using boolean operations on sets. |
451 | | |
452 | | Arguments: |
453 | | c the character |
454 | | data_start points to the start of the ECLASS data |
455 | | data_end points one-past-the-last of the ECLASS data |
456 | | utf TRUE if in UTF mode |
457 | | |
458 | | Returns: TRUE if character matches, else FALSE |
459 | | */ |
460 | | |
461 | | BOOL |
462 | | PRIV(eclass)(uint32_t c, PCRE2_SPTR data_start, PCRE2_SPTR data_end, |
463 | | const uint8_t *char_lists_end, BOOL utf) |
464 | 4.62k | { |
465 | 4.62k | PCRE2_SPTR ptr = data_start; |
466 | 4.62k | PCRE2_UCHAR flags; |
467 | 4.62k | uint32_t stack = 0; |
468 | 4.62k | int stack_depth = 0; |
469 | | |
470 | 4.62k | PCRE2_ASSERT(data_start < data_end); |
471 | 4.62k | flags = *ptr++; |
472 | 4.62k | PCRE2_ASSERT((flags & ECL_MAP) == 0 || |
473 | 4.62k | (data_end - ptr) >= 32 / (int)sizeof(PCRE2_UCHAR)); |
474 | | |
475 | | /* Code points < 256 are matched against a bitmap, if one is present. |
476 | | Otherwise all codepoints are checked later. */ |
477 | | |
478 | 4.62k | if ((flags & ECL_MAP) != 0) |
479 | 2.53k | { |
480 | 2.53k | if (c < 256) |
481 | 1.44k | return (((const uint8_t *)ptr)[c/8] & (1u << (c&7))) != 0; |
482 | | |
483 | | /* Skip the bitmap. */ |
484 | 1.09k | ptr += 32 / sizeof(PCRE2_UCHAR); |
485 | 1.09k | } |
486 | | |
487 | | /* Do a little loop, until we reach the end of the ECLASS. */ |
488 | 14.3k | while (ptr < data_end) |
489 | 11.1k | { |
490 | 11.1k | switch (*ptr) |
491 | 11.1k | { |
492 | 1.45k | case ECL_AND: |
493 | 1.45k | ++ptr; |
494 | 1.45k | stack = (stack >> 1) & (stack | ~(uint32_t)1u); |
495 | 1.45k | PCRE2_ASSERT(stack_depth >= 2); |
496 | 1.45k | --stack_depth; |
497 | 1.45k | break; |
498 | | |
499 | 718 | case ECL_OR: |
500 | 718 | ++ptr; |
501 | 718 | stack = (stack >> 1) | (stack & (uint32_t)1u); |
502 | 718 | PCRE2_ASSERT(stack_depth >= 2); |
503 | 718 | --stack_depth; |
504 | 718 | break; |
505 | | |
506 | 1.43k | case ECL_XOR: |
507 | 1.43k | ++ptr; |
508 | 1.43k | stack = (stack >> 1) ^ (stack & (uint32_t)1u); |
509 | 1.43k | PCRE2_ASSERT(stack_depth >= 2); |
510 | 1.43k | --stack_depth; |
511 | 1.43k | break; |
512 | | |
513 | 764 | case ECL_NOT: |
514 | 764 | ++ptr; |
515 | 764 | stack ^= (uint32_t)1u; |
516 | 764 | PCRE2_ASSERT(stack_depth >= 1); |
517 | 764 | break; |
518 | | |
519 | 6.79k | case ECL_XCLASS: |
520 | 6.79k | { |
521 | 6.79k | uint32_t matched = PRIV(xclass)(c, ptr + 1 + LINK_SIZE, char_lists_end, utf); |
522 | | |
523 | 6.79k | ptr += GET(ptr, 1); |
524 | 6.79k | stack = (stack << 1) | matched; |
525 | 6.79k | ++stack_depth; |
526 | 6.79k | break; |
527 | 0 | } |
528 | | |
529 | | /* This should never occur, but compilers may mutter if there is no |
530 | | default. */ |
531 | | |
532 | | /* LCOV_EXCL_START */ |
533 | 0 | default: |
534 | 0 | PCRE2_DEBUG_UNREACHABLE(); |
535 | 0 | return FALSE; |
536 | | /* LCOV_EXCL_STOP */ |
537 | 11.1k | } |
538 | 11.1k | } |
539 | | |
540 | 3.18k | PCRE2_ASSERT(stack_depth == 1); |
541 | 3.18k | (void)stack_depth; /* Ignore unused variable, if assertions are disabled. */ |
542 | | |
543 | | /* The final bit left on the stack now holds the match result. */ |
544 | 3.18k | return (stack & 1u) != 0; |
545 | 3.18k | } |
546 | | |
547 | | /* End of pcre2_xclass.c */ |