diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 13:05:23 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 13:05:23 +0300 |
commit | bc59289b7a25219ea2179554dc26c88e533250a5 (patch) | |
tree | 7e2e3280bc9920649cd0a4f1e2a8efb54c0d719b | |
parent | eaeccc1d99458f17b535a8fb3ae7479f8d013d7f (diff) | |
download | php-git-bc59289b7a25219ea2179554dc26c88e533250a5.tar.gz |
Fixed indirect modification of magic method arguments.
-rw-r--r-- | Zend/tests/bug75420.1.phpt | 18 | ||||
-rw-r--r-- | Zend/tests/bug75420.2.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/bug75420.3.phpt | 18 | ||||
-rw-r--r-- | Zend/tests/bug75420.4.phpt | 17 | ||||
-rw-r--r-- | Zend/tests/bug75420.5.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/bug75420.6.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/bug75420.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 25 |
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 22455b9254..8028b2ee5b 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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); |