Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/pcre2/src/pcre2_compile_cgroup.c
14710 views
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
#include "pcre2_compile.h"
43
44
/*************************************************
45
* Compute the hash code from a capture name *
46
*************************************************/
47
48
/* This function returns with a simple hash code
49
computed from the name of a capture group.
50
51
Arguments:
52
name name of the capture group
53
length the length of the name
54
55
Returns: hash code
56
*/
57
58
uint16_t
59
PRIV(compile_get_hash_from_name)(PCRE2_SPTR name, uint32_t length)
60
{
61
uint16_t hash;
62
63
PCRE2_ASSERT(length > 0);
64
65
hash = (uint16_t)((name[0] & 0x7f) | ((name[length - 1] & 0xff) << 7));
66
PCRE2_ASSERT(hash <= NAMED_GROUP_HASH_MASK);
67
return hash;
68
}
69
70
71
/*************************************************
72
* Get the descriptor of a known named capture *
73
*************************************************/
74
75
/* This function returns the descriptor in the
76
named group list of a known capture group.
77
78
Arguments:
79
name name of the capture group
80
length the length of the name
81
82
Returns: pointer to the descriptor when found,
83
NULL otherwise
84
*/
85
86
named_group *
87
PRIV(compile_find_named_group)(PCRE2_SPTR name,
88
uint32_t length, compile_block *cb)
89
{
90
uint16_t hash = PRIV(compile_get_hash_from_name)(name, length);
91
named_group *ng;
92
named_group *end = cb->named_groups + cb->names_found;
93
94
for (ng = cb->named_groups; ng < end; ng++)
95
if (length == ng->length && hash == NAMED_GROUP_GET_HASH(ng) &&
96
PRIV(strncmp)(name, ng->name, length) == 0) return ng;
97
98
return NULL;
99
}
100
101
102
/*************************************************
103
* Add an entry to the name/number table *
104
*************************************************/
105
106
/* This function is called between compiling passes to add an entry to the
107
name/number table, maintaining alphabetical order. Checking for permitted
108
and forbidden duplicates has already been done.
109
110
Arguments:
111
cb the compile data block
112
nb named group entry
113
tablecount the count of names in the table so far
114
115
Returns: new tablecount
116
*/
117
118
uint32_t
119
PRIV(compile_add_name_to_table)(compile_block *cb,
120
named_group *ng, uint32_t tablecount)
121
{
122
uint32_t i;
123
PCRE2_SPTR name = ng->name;
124
int length = ng->length;
125
uint32_t duplicate_count = 1;
126
127
PCRE2_UCHAR *slot = cb->name_table;
128
129
PCRE2_ASSERT(length > 0);
130
131
if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0)
132
{
133
named_group *ng_it;
134
named_group *end = cb->named_groups + cb->names_found;
135
136
for (ng_it = ng + 1; ng_it < end; ng_it++)
137
if (ng_it->name == name) duplicate_count++;
138
}
139
140
for (i = 0; i < tablecount; i++)
141
{
142
int crc = memcmp(name, slot + IMM2_SIZE, CU2BYTES(length));
143
if (crc == 0 && slot[IMM2_SIZE + length] != 0)
144
crc = -1; /* Current name is a substring */
145
146
/* Make space in the table and break the loop for an earlier name. For a
147
duplicate or later name, carry on. We do this for duplicates so that in the
148
simple case (when ?(| is not used) they are in order of their numbers. In all
149
cases they are in the order in which they appear in the pattern. */
150
151
if (crc < 0)
152
{
153
(void)memmove(slot + cb->name_entry_size * duplicate_count, slot,
154
CU2BYTES((tablecount - i) * cb->name_entry_size));
155
break;
156
}
157
158
/* Continue the loop for a later or duplicate name */
159
160
slot += cb->name_entry_size;
161
}
162
163
tablecount += duplicate_count;
164
165
while (TRUE)
166
{
167
PUT2(slot, 0, ng->number);
168
memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));
169
170
/* Add a terminating zero and fill the rest of the slot with zeroes so that
171
the memory is all initialized. Otherwise valgrind moans about uninitialized
172
memory when saving serialized compiled patterns. */
173
174
memset(slot + IMM2_SIZE + length, 0,
175
CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));
176
177
if (--duplicate_count == 0) break;
178
179
while (TRUE)
180
{
181
++ng;
182
if (ng->name == name) break;
183
}
184
185
slot += cb->name_entry_size;
186
}
187
188
return tablecount;
189
}
190
191
192
/*************************************************
193
* Find details of duplicate group names *
194
*************************************************/
195
196
/* This is called from compile_branch() when it needs to know the index and
197
count of duplicates in the names table when processing named backreferences,
198
either directly, or as conditions.
199
200
Arguments:
201
name points to the name
202
length the length of the name
203
indexptr where to put the index
204
countptr where to put the count of duplicates
205
errorcodeptr where to put an error code
206
cb the compile block
207
208
Returns: TRUE if OK, FALSE if not, error code set
209
*/
210
211
BOOL
212
PRIV(compile_find_dupname_details)(PCRE2_SPTR name, uint32_t length,
213
int *indexptr, int *countptr, int *errorcodeptr, compile_block *cb)
214
{
215
uint32_t i, groupnumber;
216
int count;
217
PCRE2_UCHAR *slot = cb->name_table;
218
219
/* Find the first entry in the table */
220
221
for (i = 0; i < cb->names_found; i++)
222
{
223
if (PRIV(strncmp)(name, slot + IMM2_SIZE, length) == 0 &&
224
slot[IMM2_SIZE + length] == 0) break;
225
slot += cb->name_entry_size;
226
}
227
228
/* This should not occur, because this function is called only when we know we
229
have duplicate names. Give an internal error. */
230
231
/* LCOV_EXCL_START */
232
if (i >= cb->names_found)
233
{
234
PCRE2_DEBUG_UNREACHABLE();
235
*errorcodeptr = ERR53;
236
cb->erroroffset = name - cb->start_pattern;
237
return FALSE;
238
}
239
/* LCOV_EXCL_STOP */
240
241
/* Record the index and then see how many duplicates there are, updating the
242
backref map and maximum back reference as we do. */
243
244
*indexptr = i;
245
count = 0;
246
247
for (;;)
248
{
249
count++;
250
groupnumber = GET2(slot, 0);
251
cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
252
if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
253
if (++i >= cb->names_found) break;
254
slot += cb->name_entry_size;
255
if (PRIV(strncmp)(name, slot + IMM2_SIZE, length) != 0 ||
256
(slot + IMM2_SIZE)[length] != 0) break;
257
}
258
259
*countptr = count;
260
return TRUE;
261
}
262
263
264
/* Process the capture list of scan substring and recurse
265
operations. Since at least one argument must be present,
266
a 0 return value represents error. */
267
268
static size_t
269
PRIV(compile_process_capture_list)(uint32_t *pptr, PCRE2_SIZE offset,
270
int *errorcodeptr, compile_block *cb)
271
{
272
size_t i, size = 0;
273
named_group *ng;
274
PCRE2_SPTR name;
275
uint32_t length;
276
named_group *end = cb->named_groups + cb->names_found;
277
278
while (TRUE)
279
{
280
++pptr;
281
282
switch (META_CODE(*pptr))
283
{
284
case META_OFFSET:
285
GETPLUSOFFSET(offset, pptr);
286
continue;
287
288
case META_CAPTURE_NAME:
289
offset += META_DATA(*pptr);
290
length = *(++pptr);
291
name = cb->start_pattern + offset;
292
293
ng = PRIV(compile_find_named_group)(name, length, cb);
294
295
if (ng == NULL)
296
{
297
*errorcodeptr = ERR15;
298
cb->erroroffset = offset;
299
return 0;
300
}
301
302
if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)
303
{
304
pptr[-1] = META_CAPTURE_NUMBER;
305
pptr[0] = ng->number;
306
size++;
307
continue;
308
}
309
310
/* Remains only for duplicated names. */
311
pptr[-1] = META_CAPTURE_NAME;
312
pptr[0] = (uint32_t)(ng - cb->named_groups);
313
size++;
314
name = ng->name;
315
316
while (++ng < end)
317
if (ng->name == name) size++;
318
continue;
319
320
case META_CAPTURE_NUMBER:
321
offset += META_DATA(*pptr);
322
323
i = *(++pptr);
324
if (i > cb->bracount)
325
{
326
*errorcodeptr = ERR15;
327
cb->erroroffset = offset;
328
return 0;
329
}
330
if (i > cb->top_backref) cb->top_backref = (uint16_t)i;
331
size++;
332
continue;
333
334
default:
335
break;
336
}
337
338
PCRE2_ASSERT(size > 0);
339
return size;
340
}
341
}
342
343
344
/*******************************************************
345
* Parse the arguments of scan substring operations *
346
********************************************************/
347
348
/* This function parses the arguments of scan substring operations.
349
350
Arguments:
351
pptr_start points to the current parsed pattern pointer
352
offset argument starting offset in the pattern
353
errorcodeptr where to put an error code
354
cb the compile block
355
lengthptr NULL during the real compile phase
356
points to length accumulator during pre-compile phase
357
358
Returns: TRUE if OK, FALSE if not, error code set
359
*/
360
361
uint32_t *
362
PRIV(compile_parse_scan_substr_args)(uint32_t *pptr,
363
int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr)
364
{
365
uint8_t *captures;
366
uint8_t *capture_ptr;
367
uint8_t bit;
368
PCRE2_SPTR name;
369
named_group *ng;
370
named_group *end = cb->named_groups + cb->names_found;
371
BOOL all_found;
372
size_t size;
373
374
PCRE2_ASSERT(*pptr == META_OFFSET);
375
if (PRIV(compile_process_capture_list)(pptr - 1, 0, errorcodeptr, cb) == 0)
376
return NULL;
377
378
/* Align to bytes. Since the highest capture can
379
be equal to bracount, +1 is added before the aligning. */
380
size = (cb->bracount + 1 + 7) >> 3;
381
captures = (uint8_t*)cb->cx->memctl.malloc(size, cb->cx->memctl.memory_data);
382
if (captures == NULL)
383
{
384
*errorcodeptr = ERR21;
385
READPLUSOFFSET(cb->erroroffset, pptr);
386
return NULL;
387
}
388
389
memset(captures, 0, size);
390
391
while (TRUE)
392
{
393
switch (META_CODE(*pptr))
394
{
395
case META_OFFSET:
396
pptr++;
397
SKIPOFFSET(pptr);
398
continue;
399
400
case META_CAPTURE_NAME:
401
ng = cb->named_groups + pptr[1];
402
PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);
403
pptr += 2;
404
name = ng->name;
405
406
all_found = TRUE;
407
do
408
{
409
if (ng->name != name) continue;
410
411
capture_ptr = captures + (ng->number >> 3);
412
PCRE2_ASSERT(capture_ptr < captures + size);
413
bit = (uint8_t)(1 << (ng->number & 0x7));
414
415
if ((*capture_ptr & bit) == 0)
416
{
417
*capture_ptr |= bit;
418
all_found = FALSE;
419
}
420
}
421
while (++ng < end);
422
423
if (!all_found)
424
{
425
*lengthptr += 1 + 2 * IMM2_SIZE;
426
continue;
427
}
428
429
pptr[-2] = META_CAPTURE_NUMBER;
430
pptr[-1] = 0;
431
continue;
432
433
case META_CAPTURE_NUMBER:
434
pptr += 2;
435
436
capture_ptr = captures + (pptr[-1] >> 3);
437
PCRE2_ASSERT(capture_ptr < captures + size);
438
bit = (uint8_t)(1 << (pptr[-1] & 0x7));
439
440
if ((*capture_ptr & bit) != 0)
441
{
442
pptr[-1] = 0;
443
continue;
444
}
445
446
*capture_ptr |= bit;
447
*lengthptr += 1 + IMM2_SIZE;
448
continue;
449
450
default:
451
break;
452
}
453
454
break;
455
}
456
457
cb->cx->memctl.free(captures, cb->cx->memctl.memory_data);
458
return pptr - 1;
459
}
460
461
462
/* Implement heapsort heapify algorithm. */
463
464
static void do_heapify_u16(uint16_t *captures, size_t size, size_t i)
465
{
466
size_t max;
467
size_t left;
468
size_t right;
469
uint16_t tmp;
470
471
while (TRUE)
472
{
473
max = i;
474
left = (i << 1) + 1;
475
right = left + 1;
476
477
if (left < size && captures[left] > captures[max]) max = left;
478
if (right < size && captures[right] > captures[max]) max = right;
479
if (i == max) return;
480
481
tmp = captures[i];
482
captures[i] = captures[max];
483
captures[max] = tmp;
484
i = max;
485
}
486
}
487
488
489
/*************************************************
490
* Parse the arguments of recurse operations *
491
*************************************************/
492
493
/* This function parses the arguments of recurse operations.
494
495
Arguments:
496
pptr_start the current parsed pattern pointer
497
offset argument starting offset in the pattern
498
errorcodeptr where to put an error code
499
cb the compile block
500
lengthptr NULL during the real compile phase
501
points to length accumulator during pre-compile phase
502
503
Returns: TRUE if OK, FALSE if not, error code set
504
*/
505
506
BOOL
507
PRIV(compile_parse_recurse_args)(uint32_t *pptr_start,
508
PCRE2_SIZE offset, int *errorcodeptr, compile_block *cb)
509
{
510
uint32_t *pptr = pptr_start;
511
size_t i, size;
512
PCRE2_SPTR name;
513
named_group *ng;
514
named_group *end = cb->named_groups + cb->names_found;
515
recurse_arguments *args;
516
uint16_t *captures;
517
uint16_t *current;
518
uint16_t *captures_end;
519
uint16_t tmp;
520
521
/* Process all arguments, compute the required size. */
522
523
size = PRIV(compile_process_capture_list)(pptr, offset, errorcodeptr, cb);
524
if (size == 0) return FALSE;
525
526
args = cb->cx->memctl.malloc(
527
sizeof(recurse_arguments) + size * sizeof(uint16_t), cb->cx->memctl.memory_data);
528
529
if (args == NULL)
530
{
531
*errorcodeptr = ERR21;
532
cb->erroroffset = offset;
533
return FALSE;
534
}
535
536
args->header.next = NULL;
537
#ifdef PCRE2_DEBUG
538
args->header.type = CDATA_RECURSE_ARGS;
539
#endif
540
args->size = size;
541
542
/* Caching the pre-processed capture list. */
543
if (cb->last_data != NULL)
544
cb->last_data->next = &args->header;
545
else
546
cb->first_data = &args->header;
547
548
cb->last_data = &args->header;
549
550
/* Create the capture list size. */
551
552
captures = (uint16_t*)(args + 1);
553
554
while (TRUE)
555
{
556
++pptr;
557
558
switch (META_CODE(*pptr))
559
{
560
case META_OFFSET:
561
SKIPOFFSET(pptr);
562
continue;
563
564
case META_CAPTURE_NAME:
565
ng = cb->named_groups + *(++pptr);
566
PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);
567
*captures++ = (uint16_t)(ng->number);
568
569
name = ng->name;
570
571
while (++ng < end)
572
if (ng->name == name) *captures++ = (uint16_t)(ng->number);
573
continue;
574
575
case META_CAPTURE_NUMBER:
576
*captures++ = *(++pptr);
577
continue;
578
579
default:
580
break;
581
}
582
583
break;
584
}
585
586
PCRE2_ASSERT(size == (size_t)(captures - (uint16_t*)(args + 1)));
587
args->skip_size = (size_t)(pptr - pptr_start) - 1;
588
589
if (size == 1) return TRUE;
590
591
/* Sort captures. */
592
593
captures = (uint16_t*)(args + 1);
594
i = (size >> 1) - 1;
595
while (TRUE)
596
{
597
do_heapify_u16(captures, size, i);
598
if (i == 0) break;
599
i--;
600
}
601
602
for (i = size - 1; i > 0; i--)
603
{
604
tmp = captures[0];
605
captures[0] = captures[i];
606
captures[i] = tmp;
607
608
do_heapify_u16(captures, i, 0);
609
}
610
611
/* Remove duplicates. */
612
613
captures_end = captures + size;
614
tmp = *captures++;
615
current = captures;
616
617
while (current < captures_end)
618
{
619
if (*current != tmp)
620
{
621
tmp = *current;
622
*captures++ = tmp;
623
}
624
625
current++;
626
}
627
628
args->size = (size_t)(captures - (uint16_t*)(args + 1));
629
return TRUE;
630
}
631
632
/* End of pcre2_compile_cgroup.c */
633
634