Skip to content

Commit b3c0219

Browse files
committed
Fix autoloading of invalid symbol names
1 parent 57626b7 commit b3c0219

File tree

4 files changed

+92
-15
lines changed

4 files changed

+92
-15
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Test autoload_call_function() with invalid symbol name
3+
--FILE--
4+
<?php
5+
function customAutoloader($name) {
6+
var_dump($name);
7+
}
8+
autoload_register_function('customAutoloader');
9+
10+
try {
11+
autoload_call_function('12ayhs');
12+
} catch (\Throwable $e) {
13+
echo $e::class, ': ', $e->getMessage();
14+
}
15+
try {
16+
autoload_call_function('"');
17+
} catch (\Throwable $e) {
18+
echo $e::class, ': ', $e->getMessage();
19+
}
20+
try {
21+
autoload_call_function('');
22+
} catch (\Throwable $e) {
23+
echo $e::class, ': ', $e->getMessage();
24+
}
25+
try {
26+
autoload_call_function("al\no");
27+
} catch (\Throwable $e) {
28+
echo $e::class, ': ', $e->getMessage();
29+
}
30+
?>
31+
--EXPECT--
32+
string(6) "12ayhs"
33+
string(1) """
34+
string(0) ""
35+
string(4) "al
36+
o"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Dynamic autoload with invalid symbol name in variable
3+
--FILE--
4+
<?php
5+
function customAutoloader($name) {
6+
var_dump($name);
7+
}
8+
autoload_register_function('customAutoloader');
9+
$name = '12ayhs';
10+
11+
try {
12+
$name();
13+
} catch (\Throwable $e) {
14+
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
15+
}
16+
$name = '"';
17+
try {
18+
$name();
19+
} catch (\Throwable $e) {
20+
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
21+
}
22+
$name = '';
23+
try {
24+
$name();
25+
} catch (\Throwable $e) {
26+
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
27+
}
28+
$name = "al\no";
29+
try {
30+
$name();
31+
} catch (\Throwable $e) {
32+
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
33+
}
34+
?>
35+
--EXPECT--
36+
string(6) "12ayhs"
37+
Error: Call to undefined function 12ayhs()
38+
Error: Call to undefined function "()
39+
Error: Call to undefined function ()
40+
Error: Call to undefined function al
41+
o()

Zend/zend_execute.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_
4646
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value);
4747
ZEND_API void execute_ex(zend_execute_data *execute_data);
4848
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
49-
ZEND_API bool zend_is_valid_class_name(zend_string *name);
49+
ZEND_API bool zend_is_valid_symbol_name(zend_string *name);
50+
#define zend_is_valid_class_name(name) zend_is_valid_symbol_name((name))
5051
ZEND_API zend_function *zend_lookup_function(zend_string *name);
5152
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lcname, bool use_autoload);
5253
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);

Zend/zend_execute_API.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,17 @@ static const uint32_t valid_chars[8] = {
10561056
0xffffffff,
10571057
};
10581058

1059+
/* TODO Check first byte is not a digit? */
1060+
ZEND_API bool zend_is_valid_symbol_name(zend_string *name) {
1061+
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1062+
unsigned char c = ZSTR_VAL(name)[i];
1063+
if (!ZEND_BIT_TEST(valid_chars, c)) {
1064+
return 0;
1065+
}
1066+
}
1067+
return 1;
1068+
}
1069+
10591070
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lc_key, bool use_autoload)
10601071
{
10611072
zend_function *fbc = NULL;
@@ -1098,12 +1109,10 @@ ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *
10981109
}
10991110

11001111
/* Verify function name before passing it to the autoloader. */
1101-
/*
1102-
if (!lc_key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_class_name(name)) {
1112+
if (!lc_key && !zend_is_valid_symbol_name(name)) {
11031113
zend_string_release_ex(lc_name, 0);
11041114
return NULL;
11051115
}
1106-
*/
11071116

11081117
if (EG(in_autoload) == NULL) {
11091118
ALLOC_HASHTABLE(EG(in_autoload));
@@ -1138,16 +1147,6 @@ ZEND_API zend_function *zend_lookup_function(zend_string *name) /* {{{ */
11381147
return zend_lookup_function_ex(name, NULL, true);
11391148
}
11401149

1141-
ZEND_API bool zend_is_valid_class_name(zend_string *name) {
1142-
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
1143-
unsigned char c = ZSTR_VAL(name)[i];
1144-
if (!ZEND_BIT_TEST(valid_chars, c)) {
1145-
return 0;
1146-
}
1147-
}
1148-
return 1;
1149-
}
1150-
11511150
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *key, uint32_t flags) /* {{{ */
11521151
{
11531152
zend_class_entry *ce = NULL;
@@ -1223,7 +1222,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
12231222
}
12241223

12251224
/* Verify class name before passing it to the autoloader. */
1226-
if (!key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_class_name(name)) {
1225+
if (!key && !ZSTR_HAS_CE_CACHE(name) && !zend_is_valid_symbol_name(name)) {
12271226
zend_string_release_ex(lc_name, 0);
12281227
return NULL;
12291228
}

0 commit comments

Comments
 (0)