]> granicus.if.org Git - php/commitdiff
Fixed bugs #29767 and #31683 (__get and __set methods must not modify property name).
authorDmitry Stogov <dmitry@php.net>
Wed, 2 Feb 2005 07:19:02 +0000 (07:19 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 2 Feb 2005 07:19:02 +0000 (07:19 +0000)
NEWS
Zend/tests/bug31683.phpt [new file with mode: 0644]
Zend/zend.h
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index 70b1171167e362190496bddaf7f127f729751b2e..1196f9092a6e5886a61fa884c83b6e5b54ed8517 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,8 @@ PHP                                                                        NEWS
 - Fixed bug #31705 (parse_url() does not recognize http://foo.com#bar). (Ilia)
 - Fixed bug #31684 (dio_tcsetattr(): misconfigured termios settings).
   (elod at itfais dot com)
+- Fixed bug #31683 (changes to $name in __get($name) override future 
+  parameters). (Dmitry)
 - Fixed bug #31699 (unserialize() float problem on non-English locales). (Ilia)
 - Fixed bug #31651 (ReflectionClass::getDefaultProperties segfaults with arrays).
   (Marcus)
@@ -72,6 +74,7 @@ PHP                                                                        NEWS
   in segfault). (pdan-php at esync dot org, Tony)
 - Fixed bug #30120 (imagettftext() and imagettfbbox() accept too many
   parameters). (Jani)
+- Fixed bug #29767 (Weird behaviour of __set($name, $value)). (Dmitry)
 - Fixed bug #29733 (printf() handles repeated placeholders wrong).
   (bugs dot php dot net at bluetwanger dot de, Ilia)
 - Fixed bug #29136 (make test - libtool failure on MacOSX). (Jani)
diff --git a/Zend/tests/bug31683.phpt b/Zend/tests/bug31683.phpt
new file mode 100644 (file)
index 0000000..4e0159d
--- /dev/null
@@ -0,0 +1,97 @@
+--TEST--
+Bug #31683 (changes to $name in __get($name) override future parameters)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+class Foo implements ArrayAccess {
+
+  function __get($test) {
+    var_dump($test);         
+    $test = 'bug';
+  }
+
+  function __set($test, $val) {
+    var_dump($test);         
+    var_dump($val);
+    $test = 'bug';
+    $val = 'bug';
+  }
+
+  function __call($test, $arg) {
+    var_dump($test);         
+    $test = 'bug';
+  }
+
+  function offsetget($test) {
+    var_dump($test);         
+    $test = 'bug';
+    return 123;
+  }
+
+  function offsetset($test, $val) {
+    var_dump($test);         
+    var_dump($val);         
+    $test = 'bug';
+    $val  = 'bug';
+  }
+
+  function offsetexists($test) {
+    var_dump($test);         
+    $test = 'bug';
+  }
+
+  function offsetunset($test) {
+    var_dump($test);         
+    $test = 'bug';
+  }
+
+}
+
+$foo = new Foo();
+$a = "ok";
+
+for ($i=0; $i < 2; $i++) {
+  $foo->ok("ok");
+  $foo->ok;
+  $foo->ok = "ok";
+  $x = $foo["ok"];
+  $foo["ok"] = "ok";
+  isset($foo["ok"]);
+  unset($foo["ok"]);
+//  $foo[];
+  $foo[] = "ok";
+//  isset($foo[]);
+//  unset($foo[]);
+  $foo->$a;
+  echo "---\n";
+}
+?>
+--EXPECT--
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+NULL
+string(2) "ok"
+string(2) "ok"
+---
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+string(2) "ok"
+NULL
+string(2) "ok"
+string(2) "ok"
+---
index 7470c936f811f56a8612e5c6442e3e466e726eb4..f8fc805762c55c5f2d77ecc544251b7f39e62ccb 100644 (file)
@@ -603,6 +603,20 @@ END_EXTERN_C()
        (*ppzv_dest)->refcount = refcount;                      \
 }
 
+#define SEPARATE_ARG_IF_REF(varptr) \
+       if (PZVAL_IS_REF(varptr)) { \
+               zval *original_var = varptr; \
+               ALLOC_ZVAL(varptr); \
+               varptr->value = original_var->value; \
+               varptr->type = original_var->type; \
+               varptr->is_ref = 0; \
+               varptr->refcount = 1; \
+               zval_copy_ctor(varptr); \
+       } else { \
+               varptr->refcount++; \
+       }
+
+
 #define ZEND_MAX_RESERVED_RESOURCES    4
 
 
index 10f9dfef01fc33e212d8468ee12222bd0fbc5b72..e9353d93157d76bee2dae99923815e4b67405233 100644 (file)
@@ -72,6 +72,7 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
        INIT_PZVAL(&__get_name);
        ZVAL_STRINGL(&__get_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1, 0);
 
+       SEPARATE_ARG_IF_REF(member);
        call_args[0] = &member;
 
        /* go call the __get handler */
@@ -87,11 +88,13 @@ static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC)
           retval returns the value that is received
        */
        
-
        if (call_result == FAILURE) {
                zend_error(E_ERROR, "Could not call __get handler for class %s", Z_OBJCE_P(object)->name);
                return NULL;
        }
+
+       zval_ptr_dtor(&member);
+
        if (retval) {
                retval->refcount--;
        }
@@ -116,6 +119,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
        INIT_PZVAL(&__set_name);
        ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1, 0);
 
+       SEPARATE_ARG_IF_REF(member);
        call_args[0] = &member;
        value->refcount++;
        call_args[1] = &value;
@@ -139,6 +143,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
                return FAILURE;
        }
 
+       zval_ptr_dtor(&member);
        zval_ptr_dtor(&value);
 
        if (retval && zend_is_true(retval)) {
@@ -383,12 +388,14 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
        if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
                if(offset == NULL) {
                        /* [] construct */
-                       zval offset_null;
-                       INIT_ZVAL(offset_null);
-                       offset = &offset_null;
+                       ALLOC_INIT_ZVAL(offset);
+               } else {
+                       SEPARATE_ARG_IF_REF(offset);
                }
                zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);
 
+               zval_ptr_dtor(&offset);
+
                if (!retval) {
                        if (!EG(exception)) {
                                zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
@@ -410,14 +417,15 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
 static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
 {
        zend_class_entry *ce = Z_OBJCE_P(object);
-       zval tmp;
        
        if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
                if (!offset) {
-                       INIT_ZVAL(tmp);
-                       offset = &tmp;
+                       ALLOC_INIT_ZVAL(offset);
+               } else {
+                       SEPARATE_ARG_IF_REF(offset);
                }
                zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
+               zval_ptr_dtor(&offset);
        } else {
                zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
        }
@@ -431,7 +439,9 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
        int result;
        
        if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               SEPARATE_ARG_IF_REF(offset);
                zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);
+               zval_ptr_dtor(&offset);
                result = i_zend_is_true(retval);
                zval_ptr_dtor(&retval);
                return result;
@@ -516,7 +526,9 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
        zval *retval;
        
        if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               SEPARATE_ARG_IF_REF(offset);
                zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", &retval, offset);
+               zval_ptr_dtor(&offset);
                zval_ptr_dtor(&retval);
        } else {
                zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);