Skip to content

Commit 10435d2

Browse files
committed
ext/pcre: Handle trampolines properly for preg_replace_callback(_array)()
1 parent 8766b4c commit 10435d2

File tree

1 file changed

+18
-19
lines changed

1 file changed

+18
-19
lines changed

ext/pcre/php_pcre.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,38 +2381,38 @@ PHP_FUNCTION(preg_replace_callback)
23812381
zend_long limit = -1, flags = 0;
23822382
size_t replace_count;
23832383
zend_fcall_info fci;
2384-
zend_fcall_info_cache fcc;
2384+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
23852385

23862386
/* Get function parameters and do error-checking. */
23872387
ZEND_PARSE_PARAMETERS_START(3, 6)
23882388
Z_PARAM_ARRAY_HT_OR_STR(regex_ht, regex_str)
2389-
Z_PARAM_FUNC(fci, fcc)
2389+
Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
23902390
Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str)
23912391
Z_PARAM_OPTIONAL
23922392
Z_PARAM_LONG(limit)
23932393
Z_PARAM_ZVAL(zcount)
23942394
Z_PARAM_LONG(flags)
2395-
ZEND_PARSE_PARAMETERS_END();
2395+
ZEND_PARSE_PARAMETERS_END_EX(goto free_trampoline);
23962396

23972397
replace_count = php_preg_replace_func_impl(return_value, regex_str, regex_ht,
23982398
&fcc,
23992399
subject_str, subject_ht, limit, flags);
24002400
if (zcount) {
24012401
ZEND_TRY_ASSIGN_REF_LONG(zcount, replace_count);
24022402
}
2403+
free_trampoline:
2404+
zend_release_fcall_info_cache(&fcc);
24032405
}
24042406
/* }}} */
24052407

24062408
/* {{{ Perform Perl-style regular expression replacement using replacement callback. */
24072409
PHP_FUNCTION(preg_replace_callback_array)
24082410
{
2409-
zval zv, *replace, *zcount = NULL;
2411+
zval *replace, *zcount = NULL;
24102412
HashTable *pattern, *subject_ht;
24112413
zend_string *subject_str, *str_idx_regex;
24122414
zend_long limit = -1, flags = 0;
24132415
size_t replace_count = 0;
2414-
zend_fcall_info fci;
2415-
zend_fcall_info_cache fcc;
24162416

24172417
/* Get function parameters and do error-checking. */
24182418
ZEND_PARSE_PARAMETERS_START(2, 5)
@@ -2424,40 +2424,39 @@ PHP_FUNCTION(preg_replace_callback_array)
24242424
Z_PARAM_LONG(flags)
24252425
ZEND_PARSE_PARAMETERS_END();
24262426

2427-
fci.size = sizeof(fci);
2428-
fci.object = NULL;
2429-
fci.named_params = NULL;
2430-
24312427
if (subject_ht) {
24322428
GC_TRY_ADDREF(subject_ht);
24332429
} else {
24342430
GC_TRY_ADDREF(subject_str);
24352431
}
24362432

24372433
ZEND_HASH_FOREACH_STR_KEY_VAL(pattern, str_idx_regex, replace) {
2438-
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
2439-
zend_argument_type_error(1, "must contain only valid callbacks");
2440-
goto error;
2441-
}
24422434
if (!str_idx_regex) {
24432435
zend_argument_type_error(1, "must contain only string patterns as keys");
24442436
goto error;
24452437
}
24462438

2447-
ZVAL_COPY_VALUE(&fci.function_name, replace);
2439+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
2440+
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
2441+
zend_argument_type_error(1, "must contain only valid callbacks");
2442+
goto error;
2443+
}
24482444

2449-
replace_count += php_preg_replace_func_impl(&zv, str_idx_regex, /* regex_ht */ NULL, &fcc,
2445+
zval retval;
2446+
replace_count += php_preg_replace_func_impl(&retval, str_idx_regex, /* regex_ht */ NULL, &fcc,
24502447
subject_str, subject_ht, limit, flags);
2451-
switch (Z_TYPE(zv)) {
2448+
zend_release_fcall_info_cache(&fcc);
2449+
2450+
switch (Z_TYPE(retval)) {
24522451
case IS_ARRAY:
24532452
ZEND_ASSERT(subject_ht);
24542453
zend_array_release(subject_ht);
2455-
subject_ht = Z_ARR(zv);
2454+
subject_ht = Z_ARR(retval);
24562455
break;
24572456
case IS_STRING:
24582457
ZEND_ASSERT(subject_str);
24592458
zend_string_release(subject_str);
2460-
subject_str = Z_STR(zv);
2459+
subject_str = Z_STR(retval);
24612460
break;
24622461
case IS_NULL:
24632462
RETVAL_NULL();

0 commit comments

Comments
 (0)