stas Tue, 18 Aug 2009 20:51:49 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=287466
Log: fix crash when unexpectedly passed by-ref parameter is modified Changed paths: A php/php-src/branches/PHP_5_2/Zend/tests/unexpected_ref_bug.phpt U php/php-src/branches/PHP_5_2/Zend/zend_execute_API.c U php/php-src/branches/PHP_5_2/Zend/zend_vm_def.h U php/php-src/branches/PHP_5_2/Zend/zend_vm_execute.h A php/php-src/branches/PHP_5_2/ext/standard/tests/array/unexpected_array_mod_bug.phpt A php/php-src/branches/PHP_5_3/Zend/tests/unexpected_ref_bug.phpt U php/php-src/branches/PHP_5_3/Zend/zend_execute_API.c U php/php-src/branches/PHP_5_3/Zend/zend_vm_def.h U php/php-src/branches/PHP_5_3/Zend/zend_vm_execute.h A php/php-src/branches/PHP_5_3/ext/standard/tests/array/unexpected_array_mod_bug.phpt A php/php-src/trunk/Zend/tests/unexpected_ref_bug.phpt U php/php-src/trunk/Zend/zend_execute_API.c U php/php-src/trunk/Zend/zend_vm_def.h U php/php-src/trunk/Zend/zend_vm_execute.h
Added: php/php-src/branches/PHP_5_2/Zend/tests/unexpected_ref_bug.phpt =================================================================== --- php/php-src/branches/PHP_5_2/Zend/tests/unexpected_ref_bug.phpt (rev 0) +++ php/php-src/branches/PHP_5_2/Zend/tests/unexpected_ref_bug.phpt 2009-08-18 20:51:49 UTC (rev 287466) @@ -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. Property changes on: php/php-src/branches/PHP_5_2/Zend/tests/unexpected_ref_bug.phpt ___________________________________________________________________ Added: svn:executable + * Modified: php/php-src/branches/PHP_5_2/Zend/zend_execute_API.c =================================================================== --- php/php-src/branches/PHP_5_2/Zend/zend_execute_API.c 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_2/Zend/zend_execute_API.c 2009-08-18 20:51:49 UTC (rev 287466) @@ -921,6 +921,12 @@ 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])) { if ((*fci->params[i])->refcount>1) { Modified: php/php-src/branches/PHP_5_2/Zend/zend_vm_def.h =================================================================== --- php/php-src/branches/PHP_5_2/Zend/zend_vm_def.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_2/Zend/zend_vm_def.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -2371,6 +2371,10 @@ 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++; Modified: php/php-src/branches/PHP_5_2/Zend/zend_vm_execute.h =================================================================== --- php/php-src/branches/PHP_5_2/Zend/zend_vm_execute.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_2/Zend/zend_vm_execute.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -7584,6 +7584,10 @@ 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 @@ 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++; Added: php/php-src/branches/PHP_5_2/ext/standard/tests/array/unexpected_array_mod_bug.phpt =================================================================== --- php/php-src/branches/PHP_5_2/ext/standard/tests/array/unexpected_array_mod_bug.phpt (rev 0) +++ php/php-src/branches/PHP_5_2/ext/standard/tests/array/unexpected_array_mod_bug.phpt 2009-08-18 20:51:49 UTC (rev 287466) @@ -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. Property changes on: php/php-src/branches/PHP_5_2/ext/standard/tests/array/unexpected_array_mod_bug.phpt ___________________________________________________________________ Added: svn:executable + * Added: php/php-src/branches/PHP_5_3/Zend/tests/unexpected_ref_bug.phpt =================================================================== --- php/php-src/branches/PHP_5_3/Zend/tests/unexpected_ref_bug.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/Zend/tests/unexpected_ref_bug.phpt 2009-08-18 20:51:49 UTC (rev 287466) @@ -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. Property changes on: php/php-src/branches/PHP_5_3/Zend/tests/unexpected_ref_bug.phpt ___________________________________________________________________ Added: svn:executable + * Modified: php/php-src/branches/PHP_5_3/Zend/zend_execute_API.c =================================================================== --- php/php-src/branches/PHP_5_3/Zend/zend_execute_API.c 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_3/Zend/zend_execute_API.c 2009-08-18 20:51:49 UTC (rev 287466) @@ -837,6 +837,12 @@ 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])) { Modified: php/php-src/branches/PHP_5_3/Zend/zend_vm_def.h =================================================================== --- php/php-src/branches/PHP_5_3/Zend/zend_vm_def.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_3/Zend/zend_vm_def.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -2686,6 +2686,10 @@ 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); Modified: php/php-src/branches/PHP_5_3/Zend/zend_vm_execute.h =================================================================== --- php/php-src/branches/PHP_5_3/Zend/zend_vm_execute.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/branches/PHP_5_3/Zend/zend_vm_execute.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -8316,6 +8316,10 @@ 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 @@ 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); Added: php/php-src/branches/PHP_5_3/ext/standard/tests/array/unexpected_array_mod_bug.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/standard/tests/array/unexpected_array_mod_bug.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/ext/standard/tests/array/unexpected_array_mod_bug.phpt 2009-08-18 20:51:49 UTC (rev 287466) @@ -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. Property changes on: php/php-src/branches/PHP_5_3/ext/standard/tests/array/unexpected_array_mod_bug.phpt ___________________________________________________________________ Added: svn:executable + * Added: php/php-src/trunk/Zend/tests/unexpected_ref_bug.phpt =================================================================== --- php/php-src/trunk/Zend/tests/unexpected_ref_bug.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/unexpected_ref_bug.phpt 2009-08-18 20:51:49 UTC (rev 287466) @@ -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. Property changes on: php/php-src/trunk/Zend/tests/unexpected_ref_bug.phpt ___________________________________________________________________ Added: svn:executable + * Modified: php/php-src/trunk/Zend/zend_execute_API.c =================================================================== --- php/php-src/trunk/Zend/zend_execute_API.c 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/trunk/Zend/zend_execute_API.c 2009-08-18 20:51:49 UTC (rev 287466) @@ -872,6 +872,12 @@ 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])) { if (Z_REFCOUNT_PP(fci->params[i]) > 1) { Modified: php/php-src/trunk/Zend/zend_vm_def.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_def.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/trunk/Zend/zend_vm_def.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -2776,6 +2776,10 @@ 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); Modified: php/php-src/trunk/Zend/zend_vm_execute.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_execute.h 2009-08-18 20:49:39 UTC (rev 287465) +++ php/php-src/trunk/Zend/zend_vm_execute.h 2009-08-18 20:51:49 UTC (rev 287466) @@ -8618,6 +8618,10 @@ 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); @@ -23163,6 +23167,10 @@ 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);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php