]> granicus.if.org Git - php/commitdiff
Fixed indirect modification of magic method arguments.
authorDmitry Stogov <dmitry@zend.com>
Thu, 26 Oct 2017 10:05:23 +0000 (13:05 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 26 Oct 2017 10:05:23 +0000 (13:05 +0300)
Zend/tests/bug75420.1.phpt [new file with mode: 0644]
Zend/tests/bug75420.2.phpt [new file with mode: 0644]
Zend/tests/bug75420.3.phpt [new file with mode: 0644]
Zend/tests/bug75420.4.phpt [new file with mode: 0644]
Zend/tests/bug75420.5.phpt [new file with mode: 0644]
Zend/tests/bug75420.6.phpt [new file with mode: 0644]
Zend/tests/bug75420.phpt
Zend/zend_object_handlers.c

diff --git a/Zend/tests/bug75420.1.phpt b/Zend/tests/bug75420.1.phpt
new file mode 100644 (file)
index 0000000..80e951a
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #75420.1 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["name"] = 24; return true; }
+       public function __get($x) { var_dump($x); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+var_dump($obj->$name ?? 12);
+var_dump($name);
+?>
+--EXPECT--
+string(3) "foo"
+int(42)
+int(24)
diff --git a/Zend/tests/bug75420.2.phpt b/Zend/tests/bug75420.2.phpt
new file mode 100644 (file)
index 0000000..3e7a63f
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #75420.2 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["name"] = 24; return true; }
+       public function __get($x) { var_dump($x); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+$name = str_repeat($name, 2);
+var_dump($obj->$name ?? 12);
+var_dump($name);
+?>
+--EXPECT--
+string(6) "foofoo"
+int(42)
+int(24)
+
diff --git a/Zend/tests/bug75420.3.phpt b/Zend/tests/bug75420.3.phpt
new file mode 100644 (file)
index 0000000..4810618
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #75420.3 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["name"] = 24; return true; }
+       public function __get($x) { var_dump($x); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+var_dump(empty($obj->$name));
+var_dump($name);
+?>
+--EXPECT--
+string(3) "foo"
+bool(false)
+int(24)
diff --git a/Zend/tests/bug75420.4.phpt b/Zend/tests/bug75420.4.phpt
new file mode 100644 (file)
index 0000000..e25bf31
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #75420.4 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["name"] = 24; return true; }
+       public function __get($x) { var_dump($x); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+$name = str_repeat($name, 2);
+var_dump(empty($obj->$name));
+?>
+--EXPECT--
+string(6) "foofoo"
+bool(false)
diff --git a/Zend/tests/bug75420.5.phpt b/Zend/tests/bug75420.5.phpt
new file mode 100644 (file)
index 0000000..85fedc4
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #75420.5 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["obj"] = 24; return true; }
+       public function __get($x) { var_dump($this); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+var_dump($obj->$name ?? 12);
+var_dump($obj);
+?>
+--EXPECT--
+object(Test)#1 (0) {
+}
+int(42)
+int(24)
diff --git a/Zend/tests/bug75420.6.phpt b/Zend/tests/bug75420.6.phpt
new file mode 100644 (file)
index 0000000..e4aa230
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Bug #75420.6 (Indirect modification of magic method argument)
+--FILE--
+<?php
+class Test {
+       public function __isset($x) { $GLOBALS["obj"] = 24; return true; }
+       public function __get($x) { var_dump($this); return 42; }
+}
+
+$obj = new Test;
+$name = "foo";
+var_dump(empty($obj->$name));
+var_dump($obj);
+?>
+--EXPECT--
+object(Test)#1 (0) {
+}
+bool(false)
+int(24)
index 969a4a04178bf4be306a959c2db5089b3838be30..5528ad301b222363f46aa7238a5e2ec64def2dcb 100644 (file)
@@ -13,5 +13,5 @@ $name = "foo";
 var_dump($obj->$name ?? 12);
 ?>
 --EXPECT--
-int(24)
+string(3) "foo"
 int(42)
index 22455b9254d5c5d9ee6ae9e17178bbe65b64e902..8028b2ee5b46d4b8c00a92f98cf6d85a461557fc 100644 (file)
@@ -507,7 +507,7 @@ static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member
 zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
 {
        zend_object *zobj;
-       zval tmp_member;
+       zval tmp_member, tmp_object;
        zval *retval;
        uint32_t property_offset;
        zend_long *guard = NULL;
@@ -543,12 +543,18 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                goto exit;
        }
 
+       ZVAL_UNDEF(&tmp_object);
+
        /* magic isset */
        if ((type == BP_VAR_IS) && zobj->ce->__isset) {
-               zval tmp_object, tmp_result;
+               zval tmp_result;
                guard = zend_get_property_guard(zobj, Z_STR_P(member));
 
                if (!((*guard) & IN_ISSET)) {
+                       if (Z_TYPE(tmp_member) == IS_UNDEF) {
+                               ZVAL_COPY(&tmp_member, member);
+                               member = &tmp_member;
+                       }
                        ZVAL_COPY(&tmp_object, object);
                        ZVAL_UNDEF(&tmp_result);
 
@@ -563,7 +569,6 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                                goto exit;
                        }
 
-                       zval_ptr_dtor(&tmp_object);
                        zval_ptr_dtor(&tmp_result);
                }
        }
@@ -574,10 +579,10 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                        guard = zend_get_property_guard(zobj, Z_STR_P(member));
                }
                if (!((*guard) & IN_GET)) {
-                       zval tmp_object;
-
                        /* have getter - try with it! */
-                       ZVAL_COPY(&tmp_object, object);
+                       if (Z_TYPE(tmp_object) == IS_UNDEF) {
+                               ZVAL_COPY(&tmp_object, object);
+                       }
                        *guard |= IN_GET; /* prevent circular getting */
                        zend_std_call_getter(&tmp_object, member, rv);
                        *guard &= ~IN_GET;
@@ -597,6 +602,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                        zval_ptr_dtor(&tmp_object);
                        goto exit;
                } else {
+                       zval_ptr_dtor(&tmp_object);
                        if (Z_STRVAL_P(member)[0] == '\0') {
                                if (Z_STRLEN_P(member) == 0) {
                                        zend_throw_error(NULL, "Cannot access empty property");
@@ -610,6 +616,9 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
                        }
                }
        }
+
+       zval_ptr_dtor(&tmp_object);
+
        if ((type != BP_VAR_IS)) {
                zend_error(E_NOTICE,"Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), Z_STRVAL_P(member));
        }
@@ -1510,6 +1519,10 @@ found:
                        zval tmp_object;
 
                        /* have issetter - try with it! */
+                       if (Z_TYPE(tmp_member) == IS_UNDEF) {
+                               ZVAL_COPY(&tmp_member, member);
+                               member = &tmp_member;
+                       }
                        ZVAL_COPY(&tmp_object, object);
                        (*guard) |= IN_ISSET; /* prevent circular getting */
                        zend_std_call_issetter(&tmp_object, member, &rv);