Skip to content

Commit 64f7aa1

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

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

ext/pcre/php_pcre.c

Lines changed: 21 additions & 19 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"
@@ -2381,38 +2384,38 @@ PHP_FUNCTION(preg_replace_callback)
23812384
zend_long limit = -1, flags = 0;
23822385
size_t replace_count;
23832386
zend_fcall_info fci;
2384-
zend_fcall_info_cache fcc;
2387+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
23852388

23862389
/* Get function parameters and do error-checking. */
23872390
ZEND_PARSE_PARAMETERS_START(3, 6)
23882391
Z_PARAM_ARRAY_HT_OR_STR(regex_ht, regex_str)
2389-
Z_PARAM_FUNC(fci, fcc)
2392+
Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
23902393
Z_PARAM_ARRAY_HT_OR_STR(subject_ht, subject_str)
23912394
Z_PARAM_OPTIONAL
23922395
Z_PARAM_LONG(limit)
23932396
Z_PARAM_ZVAL(zcount)
23942397
Z_PARAM_LONG(flags)
2395-
ZEND_PARSE_PARAMETERS_END();
2398+
ZEND_PARSE_PARAMETERS_END_EX(goto free_trampoline);
23962399

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

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

24172420
/* Get function parameters and do error-checking. */
24182421
ZEND_PARSE_PARAMETERS_START(2, 5)
@@ -2424,40 +2427,39 @@ PHP_FUNCTION(preg_replace_callback_array)
24242427
Z_PARAM_LONG(flags)
24252428
ZEND_PARSE_PARAMETERS_END();
24262429

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

24372436
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-
}
24422437
if (!str_idx_regex) {
24432438
zend_argument_type_error(1, "must contain only string patterns as keys");
24442439
goto error;
24452440
}
24462441

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

2449-
replace_count += php_preg_replace_func_impl(&zv, str_idx_regex, /* regex_ht */ NULL, &fcc,
2448+
zval retval;
2449+
replace_count += php_preg_replace_func_impl(&retval, str_idx_regex, /* regex_ht */ NULL, &fcc,
24502450
subject_str, subject_ht, limit, flags);
2451-
switch (Z_TYPE(zv)) {
2451+
zend_release_fcall_info_cache(&fcc);
2452+
2453+
switch (Z_TYPE(retval)) {
24522454
case IS_ARRAY:
24532455
ZEND_ASSERT(subject_ht);
24542456
zend_array_release(subject_ht);
2455-
subject_ht = Z_ARR(zv);
2457+
subject_ht = Z_ARR(retval);
24562458
break;
24572459
case IS_STRING:
24582460
ZEND_ASSERT(subject_str);
24592461
zend_string_release(subject_str);
2460-
subject_str = Z_STR(zv);
2462+
subject_str = Z_STR(retval);
24612463
break;
24622464
case IS_NULL:
24632465
RETVAL_NULL();

0 commit comments

Comments
 (0)