summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-10-26 13:12:52 +0300
committerDmitry Stogov <dmitry@zend.com>2017-10-26 13:12:52 +0300
commite3997b2c823415cf62bffe37da1d87c1ef54f5a7 (patch)
tree927f631f7c9a74e5bd1eabe9b554e9ae4b6ca9a5 /Zend
parent887ae8a380e3ba49451a255aabf654fb95d185ba (diff)
parent177cdcf3132f61d59bd6dc27bc819a4eb3545680 (diff)
downloadphp-git-e3997b2c823415cf62bffe37da1d87c1ef54f5a7.tar.gz
Merge branch 'PHP-7.1' into PHP-7.2
* PHP-7.1: Fixed indirect modification of magic method arguments.
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/bug75420.1.phpt18
-rw-r--r--Zend/tests/bug75420.2.phpt20
-rw-r--r--Zend/tests/bug75420.3.phpt18
-rw-r--r--Zend/tests/bug75420.4.phpt17
-rw-r--r--Zend/tests/bug75420.5.phpt19
-rw-r--r--Zend/tests/bug75420.6.phpt19
-rw-r--r--Zend/tests/bug75420.phpt2
-rw-r--r--Zend/zend_object_handlers.c25
8 files changed, 131 insertions, 7 deletions
diff --git a/Zend/tests/bug75420.1.phpt b/Zend/tests/bug75420.1.phpt
new file mode 100644
index 0000000000..80e951ac9e
--- /dev/null
+++ b/Zend/tests/bug75420.1.phpt
@@ -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
index 0000000000..3e7a63ffed
--- /dev/null
+++ b/Zend/tests/bug75420.2.phpt
@@ -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
index 0000000000..4810618d15
--- /dev/null
+++ b/Zend/tests/bug75420.3.phpt
@@ -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
index 0000000000..e25bf313cb
--- /dev/null
+++ b/Zend/tests/bug75420.4.phpt
@@ -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
index 0000000000..85fedc4679
--- /dev/null
+++ b/Zend/tests/bug75420.5.phpt
@@ -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
index 0000000000..e4aa230b48
--- /dev/null
+++ b/Zend/tests/bug75420.6.phpt
@@ -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)
diff --git a/Zend/tests/bug75420.phpt b/Zend/tests/bug75420.phpt
index 969a4a0417..5528ad301b 100644
--- a/Zend/tests/bug75420.phpt
+++ b/Zend/tests/bug75420.phpt
@@ -13,5 +13,5 @@ $name = "foo";
var_dump($obj->$name ?? 12);
?>
--EXPECT--
-int(24)
+string(3) "foo"
int(42)
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index b3cdc92bed..bb1521a5e0 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -562,7 +562,7 @@ ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *membe
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;
uint32_t *guard = NULL;
@@ -598,12 +598,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);
@@ -618,7 +624,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);
}
}
@@ -629,10 +634,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;
@@ -652,6 +657,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' && Z_STRLEN_P(member) != 0) {
zend_throw_error(NULL, "Cannot access property started with '\\0'");
retval = &EG(uninitialized_zval);
@@ -659,6 +665,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));
}
@@ -1564,6 +1573,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);