summaryrefslogtreecommitdiff
path: root/ext/spl/php_spl.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-01-09 15:11:33 +0300
committerDmitry Stogov <dmitry@zend.com>2017-01-09 15:11:33 +0300
commit4f1b24d97447434973a06bdc70fc1670de17bd80 (patch)
tree6570522246baddfa9dab10feb4fea219a42aee8e /ext/spl/php_spl.c
parent63e08cbef73120ae2b1cbe0a4fc89bc9d7ef0187 (diff)
downloadphp-git-4f1b24d97447434973a06bdc70fc1670de17bd80.tar.gz
Fixed bug #73896 (spl_autoload() crashes when calls magic _call())
Diffstat (limited to 'ext/spl/php_spl.c')
-rw-r--r--ext/spl/php_spl.c26
1 files changed, 25 insertions, 1 deletions
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, &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);
@@ -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 */