Skip to content

Commit c6ba284

Browse files
committed
Merge branch 'PHP-7.1' of git.php.net:/php-src into PHP-7.1
* 'PHP-7.1' of git.php.net:/php-src: Fixed bug #73896 (spl_autoload() crashes when calls magic _call())
2 parents 2992f41 + 5753a75 commit c6ba284

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ PHP NEWS
2020
- Session:
2121
. Fixed bug #69582 (session not readable by root in CLI). (EvgeniySpinov)
2222

23+
- SPL:
24+
. Fixed bug #73896 (spl_autoload() crashes when calls magic _call()). (Dmitry)
25+
2326
- Standard:
2427
. Fixed bug #69442 (closing of fd incorrect when PTS enabled). (jaytaph)
2528
. Fixed bug #47021 (SoapClient stumbles over WSDL delivered with

ext/spl/php_spl.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ static void autoload_func_info_dtor(zval *element)
380380
if (!Z_ISUNDEF(alfi->closure)) {
381381
zval_ptr_dtor(&alfi->closure);
382382
}
383+
if (alfi->func_ptr &&
384+
UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
385+
zend_string_release(alfi->func_ptr->common.function_name);
386+
zend_free_trampoline(alfi->func_ptr);
387+
}
383388
efree(alfi);
384389
}
385390

@@ -405,7 +410,15 @@ PHP_FUNCTION(spl_autoload_call)
405410
zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos);
406411
while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) {
407412
alfi = zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos);
408-
zend_call_method(Z_ISUNDEF(alfi->obj)? NULL : &alfi->obj, alfi->ce, &alfi->func_ptr, ZSTR_VAL(func_name), ZSTR_LEN(func_name), retval, 1, class_name, NULL);
413+
if (UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
414+
zend_function *copy = emalloc(sizeof(zend_op_array));
415+
416+
memcpy(copy, alfi->func_ptr, sizeof(zend_op_array));
417+
copy->op_array.function_name = zend_string_copy(alfi->func_ptr->op_array.function_name);
418+
zend_call_method(Z_ISUNDEF(alfi->obj)? NULL : &alfi->obj, alfi->ce, &copy, ZSTR_VAL(func_name), ZSTR_LEN(func_name), retval, 1, class_name, NULL);
419+
} else {
420+
zend_call_method(Z_ISUNDEF(alfi->obj)? NULL : &alfi->obj, alfi->ce, &alfi->func_ptr, ZSTR_VAL(func_name), ZSTR_LEN(func_name), retval, 1, class_name, NULL);
421+
}
409422
zend_exception_save();
410423
if (retval) {
411424
zval_ptr_dtor(retval);
@@ -567,13 +580,24 @@ PHP_FUNCTION(spl_autoload_register)
567580
}
568581
}
569582

583+
if (UNEXPECTED(alfi.func_ptr == &EG(trampoline))) {
584+
zend_function *copy = emalloc(sizeof(zend_op_array));
585+
586+
memcpy(copy, alfi.func_ptr, sizeof(zend_op_array));
587+
alfi.func_ptr->common.function_name = NULL;
588+
alfi.func_ptr = copy;
589+
}
570590
if (zend_hash_add_mem(SPL_G(autoload_functions), lc_name, &alfi, sizeof(autoload_func_info)) == NULL) {
571591
if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
572592
Z_DELREF(alfi.obj);
573593
}
574594
if (!Z_ISUNDEF(alfi.closure)) {
575595
Z_DELREF(alfi.closure);
576596
}
597+
if (UNEXPECTED(alfi.func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
598+
zend_string_release(alfi.func_ptr->common.function_name);
599+
zend_free_trampoline(alfi.func_ptr);
600+
}
577601
}
578602
if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
579603
/* Move the newly created element to the head of the hashtable */

ext/spl/tests/bug73896.phpt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Bug #73896 (spl_autoload() crashes when calls magic _call())
3+
--FILE--
4+
<?php
5+
class Registrator {
6+
public static function call($callable, array $args) {
7+
return call_user_func_array($callable, [$args]);
8+
}
9+
}
10+
11+
class teLoader {
12+
public function __construct() {
13+
Registrator::call('spl_autoload_register', [$this, 'autoload']);
14+
}
15+
16+
public function __call($method, $args) {
17+
$this->doSomething();
18+
}
19+
20+
protected function autoload($class) {
21+
die("Protected autoload() called!\n");
22+
}
23+
24+
public function doSomething() {
25+
throw new teException();
26+
}
27+
}
28+
29+
$teLoader = new teLoader();
30+
31+
try {
32+
new teChild();
33+
} catch (Throwable $e) {
34+
echo "Exception: ", $e->getMessage() , "\n";
35+
}
36+
?>
37+
--EXPECT--
38+
Exception: Class 'teException' not found

0 commit comments

Comments
 (0)