diff options
author | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 13:11:59 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2017-10-26 13:11:59 +0300 |
commit | 177cdcf3132f61d59bd6dc27bc819a4eb3545680 (patch) | |
tree | 5a43a69923e5de5d88528387956b1d23f42e4692 | |
parent | 6b637ac589b890ab1e05e6e19dbfc4e07fe923e2 (diff) | |
parent | bc59289b7a25219ea2179554dc26c88e533250a5 (diff) | |
download | php-git-177cdcf3132f61d59bd6dc27bc819a4eb3545680.tar.gz |
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0:
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 ed972c718c..e8530340fb 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -574,7 +574,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; @@ -610,12 +610,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); @@ -630,7 +636,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); } } @@ -641,10 +646,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; @@ -664,6 +669,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); @@ -671,6 +677,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)); } @@ -1581,6 +1590,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); |