From: Dmitry Stogov Date: Mon, 9 Jan 2017 12:11:33 +0000 (+0300) Subject: Fixed bug #73896 (spl_autoload() crashes when calls magic _call()) X-Git-Tag: php-7.1.2RC1~105^2^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f1b24d97447434973a06bdc70fc1670de17bd80;p=php Fixed bug #73896 (spl_autoload() crashes when calls magic _call()) --- diff --git a/NEWS b/NEWS index 75b850933a..3a8919aece 100644 --- a/NEWS +++ b/NEWS @@ -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 diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 4a63ebcf5e..aab10e568a 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -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); } @@ -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, ©, 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); @@ -568,6 +581,13 @@ 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); @@ -575,6 +595,10 @@ PHP_FUNCTION(spl_autoload_register) 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 */ diff --git a/ext/spl/tests/bug73896.phpt b/ext/spl/tests/bug73896.phpt new file mode 100644 index 0000000000..08d8f1e6c8 --- /dev/null +++ b/ext/spl/tests/bug73896.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #73896 (spl_autoload() crashes when calls magic _call()) +--FILE-- +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