Skip to content

Commit b1b23ab

Browse files
committed
Merge branch 'PHP-5.4' of git.php.net:php-src into PHP-5.4
* 'PHP-5.4' of git.php.net:php-src: Fixed Bug #66218 zend_register_functions breaks reflection
2 parents 71daf32 + 3e963f8 commit b1b23ab

File tree

4 files changed

+100
-59
lines changed

4 files changed

+100
-59
lines changed

Zend/tests/bug66218.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Bug #66218 zend_register_functions breaks reflection
3+
--SKIPIF--
4+
<?php
5+
if (PHP_SAPI != "cli") die("skip CLI only test");
6+
if (!function_exists("dl")) die("skip need dl");
7+
?>
8+
--FILE--
9+
<?php
10+
$tab = get_extension_funcs("standard");
11+
$fcts = array("dl");
12+
foreach ($fcts as $fct) {
13+
if (in_array($fct, $tab)) {
14+
echo "$fct Ok\n";
15+
}
16+
}
17+
?>
18+
Done
19+
--EXPECTF--
20+
dl Ok
21+
Done

Zend/zend_builtin_functions.c

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,36 +2452,49 @@ ZEND_FUNCTION(extension_loaded)
24522452
Returns an array with the names of functions belonging to the named extension */
24532453
ZEND_FUNCTION(get_extension_funcs)
24542454
{
2455-
char *extension_name;
2456-
int extension_name_len;
2455+
char *extension_name, *lcname;
2456+
int extension_name_len, array;
24572457
zend_module_entry *module;
2458-
const zend_function_entry *func;
2459-
2458+
HashPosition iterator;
2459+
zend_function *zif;
24602460
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &extension_name, &extension_name_len) == FAILURE) {
24612461
return;
24622462
}
2463-
24642463
if (strncasecmp(extension_name, "zend", sizeof("zend"))) {
2465-
char *lcname = zend_str_tolower_dup(extension_name, extension_name_len);
2466-
if (zend_hash_find(&module_registry, lcname,
2467-
extension_name_len+1, (void**)&module) == FAILURE) {
2468-
efree(lcname);
2469-
RETURN_FALSE;
2470-
}
2464+
lcname = zend_str_tolower_dup(extension_name, extension_name_len);
2465+
} else {
2466+
lcname = estrdup("core");
2467+
}
2468+
if (zend_hash_find(&module_registry, lcname,
2469+
extension_name_len+1, (void**)&module) == FAILURE) {
24712470
efree(lcname);
2471+
RETURN_FALSE;
2472+
}
24722473

2473-
if (!(func = module->functions)) {
2474-
RETURN_FALSE;
2475-
}
2474+
zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
2475+
if (module->functions) {
2476+
/* avoid BC break, if functions list is empty, will return an empty array */
2477+
array_init(return_value);
2478+
array = 1;
24762479
} else {
2477-
func = builtin_functions;
2480+
array = 0;
2481+
}
2482+
while (zend_hash_get_current_data_ex(CG(function_table), (void **) &zif, &iterator) == SUCCESS) {
2483+
if (zif->common.type==ZEND_INTERNAL_FUNCTION
2484+
&& zif->internal_function.module == module) {
2485+
if (!array) {
2486+
array_init(return_value);
2487+
array = 1;
2488+
}
2489+
add_next_index_string(return_value, zif->common.function_name, 1);
2490+
}
2491+
zend_hash_move_forward_ex(CG(function_table), &iterator);
24782492
}
24792493

2480-
array_init(return_value);
2494+
efree(lcname);
24812495

2482-
while (func->fname) {
2483-
add_next_index_string(return_value, func->fname, 1);
2484-
func++;
2496+
if (!array) {
2497+
RETURN_FALSE;
24852498
}
24862499
}
24872500
/* }}} */

ext/reflection/php_reflection.c

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,29 +1105,26 @@ static void _extension_string(string *str, zend_module_entry *module, char *inde
11051105
string_free(&str_constants);
11061106
}
11071107

1108-
if (module->functions && module->functions->fname) {
1108+
{
1109+
HashPosition iterator;
11091110
zend_function *fptr;
1110-
const zend_function_entry *func = module->functions;
1111-
1112-
string_printf(str, "\n - Functions {\n");
1113-
1114-
/* Is there a better way of doing this? */
1115-
while (func->fname) {
1116-
int fname_len = strlen(func->fname);
1117-
char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
1118-
1119-
if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
1120-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
1121-
func++;
1122-
efree(lc_name);
1123-
continue;
1111+
int first = 1;
1112+
1113+
zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
1114+
while (zend_hash_get_current_data_ex(CG(function_table), (void **) &fptr, &iterator) == SUCCESS) {
1115+
if (fptr->common.type==ZEND_INTERNAL_FUNCTION
1116+
&& fptr->internal_function.module == module) {
1117+
if (first) {
1118+
string_printf(str, "\n - Functions {\n");
1119+
first = 0;
1120+
}
1121+
_function_string(str, fptr, NULL, " " TSRMLS_CC);
11241122
}
1125-
1126-
_function_string(str, fptr, NULL, " " TSRMLS_CC);
1127-
efree(lc_name);
1128-
func++;
1123+
zend_hash_move_forward_ex(CG(function_table), &iterator);
1124+
}
1125+
if (!first) {
1126+
string_printf(str, "%s }\n", indent);
11291127
}
1130-
string_printf(str, "%s }\n", indent);
11311128
}
11321129

11331130
{
@@ -5242,36 +5239,25 @@ ZEND_METHOD(reflection_extension, getFunctions)
52425239
{
52435240
reflection_object *intern;
52445241
zend_module_entry *module;
5242+
HashPosition iterator;
5243+
zval *function;
5244+
zend_function *fptr;
52455245

52465246
if (zend_parse_parameters_none() == FAILURE) {
52475247
return;
52485248
}
52495249
GET_REFLECTION_OBJECT_PTR(module);
52505250

52515251
array_init(return_value);
5252-
if (module->functions) {
5253-
zval *function;
5254-
zend_function *fptr;
5255-
const zend_function_entry *func = module->functions;
5256-
5257-
/* Is there a better way of doing this? */
5258-
while (func->fname) {
5259-
int fname_len = strlen(func->fname);
5260-
char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
5261-
5262-
if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
5263-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
5264-
func++;
5265-
efree(lc_name);
5266-
continue;
5267-
}
5268-
5252+
zend_hash_internal_pointer_reset_ex(CG(function_table), &iterator);
5253+
while (zend_hash_get_current_data_ex(CG(function_table), (void **) &fptr, &iterator) == SUCCESS) {
5254+
if (fptr->common.type==ZEND_INTERNAL_FUNCTION
5255+
&& fptr->internal_function.module == module) {
52695256
ALLOC_ZVAL(function);
52705257
reflection_function_factory(fptr, NULL, function TSRMLS_CC);
5271-
add_assoc_zval_ex(return_value, func->fname, fname_len+1, function);
5272-
func++;
5273-
efree(lc_name);
5258+
add_assoc_zval(return_value, fptr->common.function_name, function);
52745259
}
5260+
zend_hash_move_forward_ex(CG(function_table), &iterator);
52755261
}
52765262
}
52775263
/* }}} */
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
ReflectionExtension::getFunctions() ##6218 zend_register_functions breaks reflection
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('reflection')) print 'skip missing reflection extension';
6+
if (PHP_SAPI != "cli") die("skip CLI only test");
7+
if (!function_exists("dl")) die("skip need dl");
8+
?>
9+
--FILE--
10+
<?php
11+
$r = new ReflectionExtension('standard');
12+
$t = $r->getFunctions();
13+
var_dump($t['dl']);
14+
?>
15+
Done
16+
--EXPECTF--
17+
object(ReflectionFunction)#%d (1) {
18+
["name"]=>
19+
string(2) "dl"
20+
}
21+
Done

0 commit comments

Comments
 (0)