@@ -114,9 +114,6 @@ static void php_free_pcre_cache(zval *data) /* {{{ */
114
114
}
115
115
#if HAVE_SETLOCALE
116
116
if ((void * )pce -> tables ) pefree ((void * )pce -> tables , 1 );
117
- if (pce -> locale ) {
118
- zend_string_release (pce -> locale );
119
- }
120
117
#endif
121
118
pefree (pce , 1 );
122
119
}
@@ -320,27 +317,30 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
320
317
pcre_cache_entry * pce ;
321
318
pcre_cache_entry new_entry ;
322
319
int rc ;
320
+ zend_string * key ;
321
+
322
+ #if HAVE_SETLOCALE
323
+ if (BG (locale_string ) &&
324
+ (ZSTR_LEN (BG (locale_string )) != 1 && ZSTR_VAL (BG (locale_string ))[0 ] != 'C' )) {
325
+ key = zend_string_alloc (ZSTR_LEN (regex ) + ZSTR_LEN (BG (locale_string )) + 1 , 0 );
326
+ memcpy (ZSTR_VAL (key ), ZSTR_VAL (BG (locale_string )), ZSTR_LEN (BG (locale_string )) + 1 );
327
+ memcpy (ZSTR_VAL (key ) + ZSTR_LEN (BG (locale_string )), ZSTR_VAL (regex ), ZSTR_LEN (regex ) + 1 );
328
+ } else
329
+ #endif
330
+ {
331
+ key = regex ;
332
+ }
323
333
324
334
/* Try to lookup the cached regex entry, and if successful, just pass
325
335
back the compiled pattern, otherwise go on and compile it. */
326
- pce = zend_hash_find_ptr (& PCRE_G (pcre_cache ), regex );
336
+ pce = zend_hash_find_ptr (& PCRE_G (pcre_cache ), key );
327
337
if (pce ) {
328
338
#if HAVE_SETLOCALE
329
- if (pce -> locale == BG (locale_string ) ||
330
- (pce -> locale && BG (locale_string ) &&
331
- ZSTR_LEN (pce -> locale ) == ZSTR_LEN (BG (locale_string )) &&
332
- !memcmp (ZSTR_VAL (pce -> locale ), ZSTR_VAL (BG (locale_string )), ZSTR_LEN (pce -> locale ))) ||
333
- (!pce -> locale &&
334
- ZSTR_LEN (BG (locale_string )) == 1 &&
335
- ZSTR_VAL (BG (locale_string ))[0 ] == 'C' ) ||
336
- (!BG (locale_string ) &&
337
- ZSTR_LEN (pce -> locale ) == 1 &&
338
- ZSTR_VAL (pce -> locale )[0 ] == 'C' )) {
339
- return pce ;
339
+ if (key != regex ) {
340
+ zend_string_release (key );
340
341
}
341
- #else
342
- return pce ;
343
342
#endif
343
+ return pce ;
344
344
}
345
345
346
346
p = ZSTR_VAL (regex );
@@ -349,6 +349,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
349
349
get to the end without encountering a delimiter. */
350
350
while (isspace ((int )* (unsigned char * )p )) p ++ ;
351
351
if (* p == 0 ) {
352
+ #if HAVE_SETLOCALE
353
+ if (key != regex ) {
354
+ zend_string_release (key );
355
+ }
356
+ #endif
352
357
php_error_docref (NULL , E_WARNING ,
353
358
p < ZSTR_VAL (regex ) + ZSTR_LEN (regex ) ? "Null byte in regex" : "Empty regular expression" );
354
359
return NULL ;
@@ -358,6 +363,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
358
363
or a backslash. */
359
364
delimiter = * p ++ ;
360
365
if (isalnum ((int )* (unsigned char * )& delimiter ) || delimiter == '\\' ) {
366
+ #if HAVE_SETLOCALE
367
+ if (key != regex ) {
368
+ zend_string_release (key );
369
+ }
370
+ #endif
361
371
php_error_docref (NULL ,E_WARNING , "Delimiter must not be alphanumeric or backslash" );
362
372
return NULL ;
363
373
}
@@ -397,6 +407,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
397
407
}
398
408
399
409
if (* pp == 0 ) {
410
+ #if HAVE_SETLOCALE
411
+ if (key != regex ) {
412
+ zend_string_release (key );
413
+ }
414
+ #endif
400
415
if (pp < ZSTR_VAL (regex ) + ZSTR_LEN (regex )) {
401
416
php_error_docref (NULL ,E_WARNING , "Null byte in regex" );
402
417
} else if (start_delimiter == end_delimiter ) {
@@ -453,13 +468,17 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
453
468
php_error_docref (NULL ,E_WARNING , "Null byte in regex" );
454
469
}
455
470
efree (pattern );
471
+ #if HAVE_SETLOCALE
472
+ if (key != regex ) {
473
+ zend_string_release (key );
474
+ }
475
+ #endif
456
476
return NULL ;
457
477
}
458
478
}
459
479
460
480
#if HAVE_SETLOCALE
461
- if (BG (locale_string ) &&
462
- (ZSTR_LEN (BG (locale_string )) != 1 || ZSTR_VAL (BG (locale_string ))[0 ] != 'C' )) {
481
+ if (key != regex ) {
463
482
tables = pcre_maketables ();
464
483
}
465
484
#endif
@@ -472,6 +491,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
472
491
tables );
473
492
474
493
if (re == NULL ) {
494
+ #if HAVE_SETLOCALE
495
+ if (key != regex ) {
496
+ zend_string_release (key );
497
+ }
498
+ #endif
475
499
php_error_docref (NULL ,E_WARNING , "Compilation failed: %s at offset %d" , error , erroffset );
476
500
efree (pattern );
477
501
if (tables ) {
@@ -516,7 +540,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
516
540
* these are supposedly the oldest ones (but not necessarily the least used
517
541
* ones).
518
542
*/
519
- if (zend_hash_num_elements (& PCRE_G (pcre_cache )) == PCRE_CACHE_SIZE ) {
543
+ if (! pce && zend_hash_num_elements (& PCRE_G (pcre_cache )) == PCRE_CACHE_SIZE ) {
520
544
int num_clean = PCRE_CACHE_SIZE / 8 ;
521
545
zend_hash_apply_with_argument (& PCRE_G (pcre_cache ), pcre_clean_cache , & num_clean );
522
546
}
@@ -527,23 +551,29 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
527
551
new_entry .preg_options = poptions ;
528
552
new_entry .compile_options = coptions ;
529
553
#if HAVE_SETLOCALE
530
- new_entry .locale = BG (locale_string ) ?
531
- ((GC_FLAGS (BG (locale_string )) & IS_STR_PERSISTENT ) ?
532
- zend_string_copy (BG (locale_string )) :
533
- zend_string_init (ZSTR_VAL (BG (locale_string )), ZSTR_LEN (BG (locale_string )), 1 )) :
534
- NULL ;
554
+ new_entry .locale = NULL ;
535
555
new_entry .tables = tables ;
536
556
#endif
537
557
new_entry .refcount = 0 ;
538
558
539
559
rc = pcre_fullinfo (re , extra , PCRE_INFO_CAPTURECOUNT , & new_entry .capture_count );
540
560
if (rc < 0 ) {
561
+ #if HAVE_SETLOCALE
562
+ if (key != regex ) {
563
+ zend_string_release (key );
564
+ }
565
+ #endif
541
566
php_error_docref (NULL , E_WARNING , "Internal pcre_fullinfo() error %d" , rc );
542
567
return NULL ;
543
568
}
544
569
545
570
rc = pcre_fullinfo (re , extra , PCRE_INFO_NAMECOUNT , & new_entry .name_count );
546
571
if (rc < 0 ) {
572
+ #if HAVE_SETLOCALE
573
+ if (key != regex ) {
574
+ zend_string_release (key );
575
+ }
576
+ #endif
547
577
php_error_docref (NULL , E_WARNING , "Internal pcre_fullinfo() error %d" , rc );
548
578
return NULL ;
549
579
}
@@ -556,15 +586,18 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
556
586
* as hash keys especually for this table.
557
587
* See bug #63180
558
588
*/
559
- if (!ZSTR_IS_INTERNED (regex ) || !(GC_FLAGS (regex ) & IS_STR_PERMANENT )) {
560
- zend_string * str = zend_string_init (ZSTR_VAL (regex ), ZSTR_LEN (regex ), 1 );
561
- GC_REFCOUNT (str ) = 0 ; /* will be incremented by zend_hash_update_mem() */
562
- ZSTR_H (str ) = ZSTR_H (regex );
563
- regex = str ;
589
+ if (!ZSTR_IS_INTERNED (key ) || !(GC_FLAGS (key ) & IS_STR_PERMANENT )) {
590
+ pce = zend_hash_str_update_mem (& PCRE_G (pcre_cache ),
591
+ ZSTR_VAL (key ), ZSTR_LEN (key ), & new_entry , sizeof (pcre_cache_entry ));
592
+ #if HAVE_SETLOCALE
593
+ if (key != regex ) {
594
+ zend_string_release (key );
595
+ }
596
+ #endif
597
+ } else {
598
+ pce = zend_hash_update_mem (& PCRE_G (pcre_cache ), key , & new_entry , sizeof (pcre_cache_entry ));
564
599
}
565
600
566
- pce = zend_hash_update_mem (& PCRE_G (pcre_cache ), regex , & new_entry , sizeof (pcre_cache_entry ));
567
-
568
601
return pce ;
569
602
}
570
603
/* }}} */
0 commit comments