]> granicus.if.org Git - php/commitdiff
Fixed bug #31525 (object reference being dropped. $this getting lost)
authorDmitry Stogov <dmitry@php.net>
Thu, 5 May 2005 17:37:25 +0000 (17:37 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 5 May 2005 17:37:25 +0000 (17:37 +0000)
Zend/tests/bug31525.phpt [new file with mode: 0755]
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
tests/lang/bug20175.phpt
tests/lang/bug21600.phpt

diff --git a/Zend/tests/bug31525.phpt b/Zend/tests/bug31525.phpt
new file mode 100755 (executable)
index 0000000..b1a01b6
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #31525 (object reference being dropped. $this getting lost)
+--INI--
+error_reporting=4095
+--FILE--
+<?php
+class Foo {
+  function getThis() {
+    return $this;
+  }
+  function destroyThis() {
+    $baz =& $this->getThis();
+  }
+}
+$bar = new Foo();
+$bar->destroyThis();
+var_dump($bar);
+?>
+--EXPECTF--
+Strict Standards: Only variables should be assigned by reference in %sbug31525.php on line 7
+object(Foo)#1 (0) {
+}
index de876333d0efedde3d6a3ab13b87e438f3660872..3f79e44eb36c342182ca8fb678fd9e80768050f8 100644 (file)
@@ -562,6 +562,12 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
        }
 }
 
+static inline zend_bool zend_is_function_or_method_call(znode *variable)
+{
+       zend_uint type = variable->u.EA.type;
+
+       return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
+}
 
 void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC)
 {
@@ -573,6 +579,11 @@ void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC)
        if (opline_is_fetch_this(last_op TSRMLS_CC)) {
                zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
        }
+       if (zend_is_function_or_method_call(rvar)) {
+               opline->extended_value = ZEND_RETURNS_FUNCTION; 
+       } else {
+               opline->extended_value = 0;
+       }
        if (result) {
                opline->result.op_type = IS_VAR;
                opline->result.u.EA.type = 0;
@@ -796,13 +807,6 @@ void zend_check_writable_variable(znode *variable)
        }
 }
 
-static inline zend_bool zend_is_function_or_method_call(znode *variable)
-{
-       zend_uint type = variable->u.EA.type;
-
-       return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
-}
-
 void zend_do_begin_variable_parse(TSRMLS_D)
 {
        zend_llist fetch_list;
index 638cec2b37067bbe5accdd0bcaa0d4c4fea0fbf4..8f4681306ce6c857bd98cd7fe68e24ddccaa3812 100644 (file)
@@ -1329,9 +1329,21 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
 
+       if (OP2_TYPE == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ASSIGN);
+       }
+
+       variable_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
index 13ecdab0d99addaf92c973a7137de3807eb11e8d..773e31b19b539bb6e8bee8025ef0405b64d56783 100644 (file)
@@ -11505,9 +11505,21 @@ static int ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
+       if (IS_VAR == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       }
+
+       variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
@@ -13267,9 +13279,21 @@ static int ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), &free_op2, BP_VAR_W TSRMLS_CC);
 
+       if (IS_CV == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               return ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       }
+
+       variable_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
@@ -22945,9 +22969,21 @@ static int ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), &free_op1, BP_VAR_W TSRMLS_CC);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = _get_zval_ptr_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
 
+       if (IS_VAR == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       }
+
+       variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), &free_op1, BP_VAR_W TSRMLS_CC);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
@@ -24707,9 +24743,21 @@ static int ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), &free_op1, BP_VAR_W TSRMLS_CC);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op2, EX(Ts), &free_op2, BP_VAR_W TSRMLS_CC);
 
+       if (IS_CV == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       }
+
+       variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline->op1, EX(Ts), &free_op1, BP_VAR_W TSRMLS_CC);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
@@ -30271,9 +30319,21 @@ static int ZEND_ASSIGN_REF_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1, free_op2;
-       zval **variable_ptr_ptr = get_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, BP_VAR_W);
+       zval **variable_ptr_ptr;
        zval **value_ptr_ptr = get_zval_ptr_ptr(&opline->op2, EX(Ts), &free_op2, BP_VAR_W);
 
+       if (opline->op2.op_type == IS_VAR &&
+           !(*value_ptr_ptr)->is_ref &&
+           opline->extended_value == ZEND_RETURNS_FUNCTION && 
+           !EX_T(opline->op2.u.var).var.fcall_returned_reference) {
+               zend_error(E_STRICT, "Only variables should be assigned by reference");
+               if (free_op2.var == NULL) {
+                       PZVAL_LOCK(*value_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+               }
+               return ZEND_ASSIGN_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+       }
+
+       variable_ptr_ptr = get_zval_ptr_ptr(&opline->op1, EX(Ts), &free_op1, BP_VAR_W);
        zend_assign_to_variable_reference(variable_ptr_ptr, value_ptr_ptr TSRMLS_CC);
 
        if (!RETURN_VALUE_UNUSED(&opline->result)) {
index 55ff7d82b80b1c9e19df2ee5fa1a34e09d64b10c..d2248e6f0eb8f2dab369b36622cd670b67971873 100644 (file)
@@ -2,6 +2,8 @@
 Bug #20175 (Static vars can't store ref to new instance)
 --SKIPIF--
 <?php if (version_compare(zend_version(),'2.0.0-dev','<')) die('skip ZE1 does not have static class members'); ?>
+--INI--
+error_reporting=4095
 --FILE--
 <?php
 print zend_version()."\n";
@@ -145,10 +147,11 @@ foo_static()
 foo:1
 bar_static()
 bar_global()
+
+Strict Standards: Only variables should be assigned by reference in %sbug20175.php on line 47
 bar:1
 bar_static()
-bar_global()
-bar:2
+bar:1
 wow_static()
 wow_global()
 wow:1
index c3f832b9eadaa1ce71ad527d3ccdcb84cd868e76..6ecf69a11f7f8816e280ffce3d1f611a18bf32fe 100644 (file)
@@ -1,5 +1,7 @@
 --TEST--
 Bug #21600 (assign by reference function call changes variable contents)
+--INI--
+error_reporting=4095
 --FILE--
 <?php
 $tmp = array();
@@ -23,11 +25,14 @@ function fubar($text){
   return $text;
 }
 ?>
---EXPECT--
+--EXPECTF--
+Strict Standards: Only variables should be assigned by reference in %sbug21600.php on line 4
 array(1) {
   ["foo"]=>
-  &string(4) "test"
+  string(4) "test"
 }
+
+Strict Standards: Only variables should be assigned by reference in %sbug21600.php on line 11
 array(1) {
   ["foo"]=>
   string(4) "test"