summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2009-08-18 20:51:49 +0000
committerStanislav Malyshev <stas@php.net>2009-08-18 20:51:49 +0000
commitd6ba6c69fb3054ed3eefb6c4c6f8ad1bfb728037 (patch)
tree322c8344f65013c732a7ce250074a1fa48722119
parent827469c94e9d3ec554dabcb79f478e06b31f6a14 (diff)
downloadphp-git-d6ba6c69fb3054ed3eefb6c4c6f8ad1bfb728037.tar.gz
fix crash when unexpectedly passed by-ref parameter is modified
-rwxr-xr-xZend/tests/unexpected_ref_bug.phpt18
-rw-r--r--Zend/zend_execute_API.c6
-rw-r--r--Zend/zend_vm_def.h4
-rw-r--r--Zend/zend_vm_execute.h8
-rwxr-xr-xext/standard/tests/array/unexpected_array_mod_bug.phpt21
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.