]> granicus.if.org Git - php/commitdiff
fix crash when unexpectedly passed by-ref parameter is modified
authorStanislav Malyshev <stas@php.net>
Tue, 18 Aug 2009 20:51:49 +0000 (20:51 +0000)
committerStanislav Malyshev <stas@php.net>
Tue, 18 Aug 2009 20:51:49 +0000 (20:51 +0000)
Zend/tests/unexpected_ref_bug.phpt [new file with mode: 0755]
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/standard/tests/array/unexpected_array_mod_bug.phpt [new file with mode: 0755]

diff --git a/Zend/tests/unexpected_ref_bug.phpt b/Zend/tests/unexpected_ref_bug.phpt
new file mode 100755 (executable)
index 0000000..61fe1aa
--- /dev/null
@@ -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.
index 935133da11ea2a2eab7aa1216e343c8d4104a91e..ee460260216f3e441df279d1f16c2a4988e73ffe 100644 (file)
@@ -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])) {
 
index 3837d0c801affd7f3261960cc49f5a9b09519aeb..8790847a01a1cdc880411d8abe2639cb8e513c29 100644 (file)
@@ -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);
index 53016c48a6b108c051047955f5f9453bc3e78218..a73f351cd92590fbf3113f738f5a3ebd9eef2862 100644 (file)
@@ -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 (executable)
index 0000000..58f2249
--- /dev/null
@@ -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.