diff options
author | Stanislav Malyshev <stas@php.net> | 2009-08-18 20:51:49 +0000 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2009-08-18 20:51:49 +0000 |
commit | d6ba6c69fb3054ed3eefb6c4c6f8ad1bfb728037 (patch) | |
tree | 322c8344f65013c732a7ce250074a1fa48722119 | |
parent | 827469c94e9d3ec554dabcb79f478e06b31f6a14 (diff) | |
download | php-git-d6ba6c69fb3054ed3eefb6c4c6f8ad1bfb728037.tar.gz |
fix crash when unexpectedly passed by-ref parameter is modified
-rwxr-xr-x | Zend/tests/unexpected_ref_bug.phpt | 18 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 4 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 8 | ||||
-rwxr-xr-x | ext/standard/tests/array/unexpected_array_mod_bug.phpt | 21 |
5 files changed, 57 insertions, 0 deletions
diff --git a/Zend/tests/unexpected_ref_bug.phpt b/Zend/tests/unexpected_ref_bug.phpt new file mode 100755 index 0000000000..61fe1aa5b1 --- /dev/null +++ b/Zend/tests/unexpected_ref_bug.phpt @@ -0,0 +1,18 @@ +--TEST-- +Crash when function parameter modified via unexpected reference +--FILE-- +<?php +function my_errorhandler($errno,$errormsg) { + global $my_var; + $my_var = 0; + return true; +} +set_error_handler("my_errorhandler"); +$my_var = str_repeat("A",64); +$data = call_user_func_array("explode",array(new StdClass(), &$my_var)); +$my_var=array(1,2,3); +$data = call_user_func_array("implode",array(&$my_var, new StdClass())); +echo "Done.\n"; +?> +--EXPECTF-- +Done. diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 935133da11..ee46026021 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -837,6 +837,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS for (i=0; i<fci->param_count; i++) { zval *param; + if(EX(function_state).function->type == ZEND_INTERNAL_FUNCTION + && !ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1) + && PZVAL_IS_REF(*fci->params[i])) { + SEPARATE_ZVAL(fci->params[i]); + } + if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1) && !PZVAL_IS_REF(*fci->params[i])) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 3837d0c801..8790847a01 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2686,6 +2686,10 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY) zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) { + ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper); + } + SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 53016c48a6..a73f351cd9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -8316,6 +8316,10 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) { + return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); @@ -22173,6 +22177,10 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); } + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.u.opline_num)) { + return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; Z_ADDREF_P(varptr); diff --git a/ext/standard/tests/array/unexpected_array_mod_bug.phpt b/ext/standard/tests/array/unexpected_array_mod_bug.phpt new file mode 100755 index 0000000000..58f2249205 --- /dev/null +++ b/ext/standard/tests/array/unexpected_array_mod_bug.phpt @@ -0,0 +1,21 @@ +--TEST-- +Crash when function parameter modified via reference +--FILE-- +<?php +function usercompare($a,$b) { + unset($GLOBALS['my_var'][2]); + return 0; +} +$my_var = array(1 => "entry_1", +2 => "entry_2", +3 => "entry_3", +4 => "entry_4", +5 => "entry_5"); +usort($my_var, "usercompare"); + +echo "Done.\n"; +?> +--EXPECTF-- + +Warning: usort(): Array was modified by the user comparison function in %s on line %d +Done. |