From 50fa1e7a2f539dc3216fe9d5da2e9a3aff6db9f3 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 18 Aug 2009 20:51:49 +0000 Subject: [PATCH] fix crash when unexpectedly passed by-ref parameter is modified --- Zend/tests/unexpected_ref_bug.phpt | 18 ++++++++++++++++ Zend/zend_execute_API.c | 6 ++++++ Zend/zend_vm_def.h | 4 ++++ Zend/zend_vm_execute.h | 8 +++++++ .../tests/array/unexpected_array_mod_bug.phpt | 21 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100755 Zend/tests/unexpected_ref_bug.phpt create mode 100755 ext/standard/tests/array/unexpected_array_mod_bug.phpt 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-- + +--EXPECTF-- +Done. diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 434f1e08f9..0e64a41c1c 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -921,6 +921,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS for (i=0; iparam_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])) { if ((*fci->params[i])->refcount>1) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index bc38c31447..33b94e1849 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2371,6 +2371,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; varptr->refcount++; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5d431eadb1..f348b31d91 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7584,6 +7584,10 @@ static int ZEND_SEND_REF_SPEC_VAR_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_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); varptr = *varptr_ptr; varptr->refcount++; @@ -20009,6 +20013,10 @@ static int 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; varptr->refcount++; 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-- + "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. -- 2.50.1