Skip to content

Commit 4d66c68

Browse files
committed
ext/pcre: Handle trampolines properly for preg_replace_callback(_array)()
1 parent c5aa69c commit 4d66c68

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

ext/pcre/php_pcre.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "php.h"
1818
#include "php_ini.h"
1919
#include "php_pcre.h"
20+
21+
#include <Optimizer/zend_func_info.h>
22+
2023
#include "ext/standard/info.h"
2124
#include "ext/standard/basic_functions.h"
2225
#include "zend_smart_str.h"
@@ -2385,33 +2388,33 @@ PHP_FUNCTION(preg_replace_callback)
23852388
/* Get function parameters and do error-checking. */
23862389
ZEND_PARSE_PARAMETERS_START(3, 6)
23872390
Z_PARAM_ARRAY_HT_OR_STR(regex_ht, regex_str)
2388-
Z_PARAM_FUNC(fci, fcc)
2391+
Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
23892392
Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str)
23902393
Z_PARAM_OPTIONAL
23912394
Z_PARAM_LONG(limit)
23922395
Z_PARAM_ZVAL(zcount)
23932396
Z_PARAM_LONG(flags)
2394-
ZEND_PARSE_PARAMETERS_END();
2397+
ZEND_PARSE_PARAMETERS_END_EX(goto free_trampoline);
23952398

23962399
replace_count = php_preg_replace_func_impl(return_value, regex_str, regex_ht,
23972400
&fcc,
23982401
subject_str, subject_ht, limit, flags);
23992402
if (zcount) {
24002403
ZEND_TRY_ASSIGN_REF_LONG(zcount, replace_count);
24012404
}
2405+
free_trampoline:
2406+
zend_release_fcall_info_cache(&fcc);
24022407
}
24032408
/* }}} */
24042409

24052410
/* {{{ Perform Perl-style regular expression replacement using replacement callback. */
24062411
PHP_FUNCTION(preg_replace_callback_array)
24072412
{
2408-
zval zv, *replace, *zcount = NULL;
2413+
zval *replace, *zcount = NULL;
24092414
HashTable *pattern, *subject_ht;
24102415
zend_string *subject_str, *str_idx_regex;
24112416
zend_long limit = -1, flags = 0;
24122417
size_t replace_count = 0;
2413-
zend_fcall_info fci;
2414-
zend_fcall_info_cache fcc;
24152418

24162419
/* Get function parameters and do error-checking. */
24172420
ZEND_PARSE_PARAMETERS_START(2, 5)
@@ -2423,40 +2426,39 @@ PHP_FUNCTION(preg_replace_callback_array)
24232426
Z_PARAM_LONG(flags)
24242427
ZEND_PARSE_PARAMETERS_END();
24252428

2426-
fci.size = sizeof(fci);
2427-
fci.object = NULL;
2428-
fci.named_params = NULL;
2429-
24302429
if (subject_ht) {
24312430
GC_TRY_ADDREF(subject_ht);
24322431
} else {
24332432
GC_TRY_ADDREF(subject_str);
24342433
}
24352434

24362435
ZEND_HASH_FOREACH_STR_KEY_VAL(pattern, str_idx_regex, replace) {
2437-
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
2438-
zend_argument_type_error(1, "must contain only valid callbacks");
2439-
goto error;
2440-
}
24412436
if (!str_idx_regex) {
24422437
zend_argument_type_error(1, "must contain only string patterns as keys");
24432438
goto error;
24442439
}
24452440

2446-
ZVAL_COPY_VALUE(&fci.function_name, replace);
2441+
zend_fcall_info_cache fcc;
2442+
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
2443+
zend_argument_type_error(1, "must contain only valid callbacks");
2444+
goto error;
2445+
}
24472446

2448-
replace_count += php_preg_replace_func_impl(&zv, str_idx_regex, /* regex_ht */ NULL, &fcc,
2447+
zval retval;
2448+
replace_count += php_preg_replace_func_impl(&retval, str_idx_regex, /* regex_ht */ NULL, &fcc,
24492449
subject_str, subject_ht, limit, flags);
2450-
switch (Z_TYPE(zv)) {
2450+
zend_release_fcall_info_cache(&fcc);
2451+
2452+
switch (Z_TYPE(retval)) {
24512453
case IS_ARRAY:
24522454
ZEND_ASSERT(subject_ht);
24532455
zend_array_release(subject_ht);
2454-
subject_ht = Z_ARR(zv);
2456+
subject_ht = Z_ARR(retval);
24552457
break;
24562458
case IS_STRING:
24572459
ZEND_ASSERT(subject_str);
24582460
zend_string_release(subject_str);
2459-
subject_str = Z_STR(zv);
2461+
subject_str = Z_STR(retval);
24602462
break;
24612463
case IS_NULL:
24622464
RETVAL_NULL();

0 commit comments

Comments
 (0)