Skip to content

Commit

Permalink
Fixed bug #73896 (spl_autoload() crashes when calls magic _call())
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Jan 9, 2017
1 parent 63e08cb commit 4f1b24d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ PHP NEWS
- Session:
. Fixed bug #69582 (session not readable by root in CLI). (EvgeniySpinov)

- SPL:
. Fixed bug #73896 (spl_autoload() crashes when calls magic _call()). (Dmitry)

- Standard:
. Fixed bug #69442 (closing of fd incorrect when PTS enabled). (jaytaph)
. Fixed bug #47021 (SoapClient stumbles over WSDL delivered with
Expand Down
26 changes: 25 additions & 1 deletion ext/spl/php_spl.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,11 @@ static void autoload_func_info_dtor(zval *element)
if (!Z_ISUNDEF(alfi->closure)) {
zval_ptr_dtor(&alfi->closure);
}
if (alfi->func_ptr &&
UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
zend_string_release(alfi->func_ptr->common.function_name);
zend_free_trampoline(alfi->func_ptr);
}
efree(alfi);
}

Expand All @@ -406,7 +411,15 @@ PHP_FUNCTION(spl_autoload_call)
zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos);
while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) {
alfi = zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos);
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);
if (UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
zend_function *copy = emalloc(sizeof(zend_op_array));

memcpy(copy, alfi->func_ptr, sizeof(zend_op_array));
copy->op_array.function_name = zend_string_copy(alfi->func_ptr->op_array.function_name);
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);
} else {
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);
}
zend_exception_save();
if (retval) {
zval_ptr_dtor(retval);
Expand Down Expand Up @@ -568,13 +581,24 @@ PHP_FUNCTION(spl_autoload_register)
}
}

if (UNEXPECTED(alfi.func_ptr == &EG(trampoline))) {
zend_function *copy = emalloc(sizeof(zend_op_array));

memcpy(copy, alfi.func_ptr, sizeof(zend_op_array));
alfi.func_ptr->common.function_name = NULL;
alfi.func_ptr = copy;
}
if (zend_hash_add_mem(SPL_G(autoload_functions), lc_name, &alfi, sizeof(autoload_func_info)) == NULL) {
if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
Z_DELREF(alfi.obj);
}
if (!Z_ISUNDEF(alfi.closure)) {
Z_DELREF(alfi.closure);
}
if (UNEXPECTED(alfi.func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
zend_string_release(alfi.func_ptr->common.function_name);
zend_free_trampoline(alfi.func_ptr);
}
}
if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
/* Move the newly created element to the head of the hashtable */
Expand Down
38 changes: 38 additions & 0 deletions ext/spl/tests/bug73896.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
--TEST--
Bug #73896 (spl_autoload() crashes when calls magic _call())
--FILE--
<?php
class Registrator {
public static function call($callable, array $args) {
return call_user_func_array($callable, [$args]);
}
}

class teLoader {
public function __construct() {
Registrator::call('spl_autoload_register', [$this, 'autoload']);
}

public function __call($method, $args) {
$this->doSomething();
}

protected function autoload($class) {
die("Protected autoload() called!\n");
}

public function doSomething() {
throw new teException();
}
}

$teLoader = new teLoader();

try {
new teChild();
} catch (Throwable $e) {
echo "Exception: ", $e->getMessage() , "\n";
}
?>
--EXPECT--
Exception: Class 'teException' not found

0 comments on commit 4f1b24d

Please sign in to comment.