com php-src: Fix #49649 - Handle property visibility changes on unserialization: NEWS ext/standard/tests/serialize/bug49649.phpt
ext/standard/tests/serialize/bug49649_1.phpt ext/standard/tests/serialize/bug49649_2.phpt ext/standard/var_unserializer.re

From: Date: Mon, 10 Jul 2017 06:27:09 +0000
Subject: com php-src: Fix #49649 - Handle property visibility changes on unserialization: NEWS ext/standard/tests/serialize/bug49649.phpt
ext/standard/tests/serialize/bug49649_1.phpt ext/standard/tests/serialize/bug49649_2.phpt ext/standard/var_unserializer.re
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-98482@lists.php.net to get a copy of this message
Commit: 7cb5bdf64a95bd70623d33d6ea122c13b01113bd Author: Pedro Magalhães <mail@pmmaga.net> Fri, 21 Apr 2017 19:37:27 +0200 Committer: Joe Watkins <krakjoe@php.net> Mon, 10 Jul 2017 07:27:09 +0100 Parents: cfacf84dc19c9ef497a67d09c02e27408830baa8 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=7cb5bdf64a95bd70623d33d6ea122c13b01113bd Log: Fix #49649 - Handle property visibility changes on unserialization Bugs: https://bugs.php.net/49649 Changed paths: M NEWS A ext/standard/tests/serialize/bug49649.phpt A ext/standard/tests/serialize/bug49649_1.phpt A ext/standard/tests/serialize/bug49649_2.phpt M ext/standard/var_unserializer.re Diff: diff --git a/NEWS b/NEWS index d9c1e5b..c88a6c5 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS . Fixed bug #74819 (wddx_deserialize() heap out-of-bound read via php_parse_date()). (Derick) . Fixed bug #74878 (Data race in ZTS builds). (Nikita) + . Fixed bug #49649 (unserialize() doesn't handle changes in property + visibility). (pmmaga) - Date: . Fixed bug #74852 (property_exists returns true on unknown DateInterval diff --git a/ext/standard/tests/serialize/bug49649.phpt b/ext/standard/tests/serialize/bug49649.phpt new file mode 100644 index 0000000..2e0a505 --- /dev/null +++ b/ext/standard/tests/serialize/bug49649.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug #49649 (unserialize() doesn't handle changes in property visibility) - to public +--FILE-- +<?php + +/** + *class Foo + *{ + * private $private = 1; + * + * protected $protected = 2; + * + * public $public = 3; + * + * public $notThere = 'old'; + * } + * + * echo base64_encode(serialize(new Foo())); + * + * The class above represents the serialized, base64_encoded string below. +*/ +$serialized = 'TzozOiJGb28iOjQ6e3M6MTI6IgBGb28AcHJpdmF0ZSI7aToxO3M6MTI6IgAqAHByb3RlY3RlZCI7aToyO3M6NjoicHVibGljIjtpOjM7czo4OiJub3RUaGVyZSI7czozOiJvbGQiO30'; + +class Foo +{ + public $public = null; + + public $protected = null; + + public $private = null; +} + +$class = unserialize(base64_decode($serialized)); +var_dump($class); +--EXPECT-- +object(Foo)#1 (4) { + ["public"]=> + int(3) + ["protected"]=> + int(2) + ["private"]=> + int(1) + ["notThere"]=> + string(3) "old" +} diff --git a/ext/standard/tests/serialize/bug49649_1.phpt b/ext/standard/tests/serialize/bug49649_1.phpt new file mode 100644 index 0000000..1ca840a --- /dev/null +++ b/ext/standard/tests/serialize/bug49649_1.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug #49649 (unserialize() doesn't handle changes in property visibility) - to protected +--FILE-- +<?php + +/** + *class Foo + *{ + * private $private = 1; + * + * protected $protected = 2; + * + * public $public = 3; + * + * public $notThere = 'old'; + * } + * + * echo base64_encode(serialize(new Foo())); + * + * The class above represents the serialized, base64_encoded string below. +*/ +$serialized = 'TzozOiJGb28iOjQ6e3M6MTI6IgBGb28AcHJpdmF0ZSI7aToxO3M6MTI6IgAqAHByb3RlY3RlZCI7aToyO3M6NjoicHVibGljIjtpOjM7czo4OiJub3RUaGVyZSI7czozOiJvbGQiO30'; + +class Foo +{ + protected $public = null; + + protected $protected = null; + + protected $private = null; +} + +$class = unserialize(base64_decode($serialized)); +var_dump($class); +--EXPECT-- +object(Foo)#1 (4) { + ["public":protected]=> + int(3) + ["protected":protected]=> + int(2) + ["private":protected]=> + int(1) + ["notThere"]=> + string(3) "old" +} diff --git a/ext/standard/tests/serialize/bug49649_2.phpt b/ext/standard/tests/serialize/bug49649_2.phpt new file mode 100644 index 0000000..e9fe429 --- /dev/null +++ b/ext/standard/tests/serialize/bug49649_2.phpt @@ -0,0 +1,45 @@ +--TEST-- +Bug #49649 (unserialize() doesn't handle changes in property visibility) - to private +--FILE-- +<?php + +/** + *class Foo + *{ + * private $private = 1; + * + * protected $protected = 2; + * + * public $public = 3; + * + * public $notThere = 'old'; + * } + * + * echo base64_encode(serialize(new Foo())); + * + * The class above represents the serialized, base64_encoded string below. +*/ +$serialized = 'TzozOiJGb28iOjQ6e3M6MTI6IgBGb28AcHJpdmF0ZSI7aToxO3M6MTI6IgAqAHByb3RlY3RlZCI7aToyO3M6NjoicHVibGljIjtpOjM7czo4OiJub3RUaGVyZSI7czozOiJvbGQiO30'; + +class Foo +{ + private $public = null; + + private $protected = null; + + private $private = null; +} + +$class = unserialize(base64_decode($serialized)); +var_dump($class); +--EXPECT-- +object(Foo)#1 (4) { + ["public":"Foo":private]=> + int(3) + ["protected":"Foo":private]=> + int(2) + ["private":"Foo":private]=> + int(1) + ["notThere"]=> + string(3) "old" +} diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 185e62d..6e7f76f 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -427,14 +427,58 @@ numeric_key: } else { if (EXPECTED(Z_TYPE(key) == IS_STRING)) { string_key: - if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { - if (Z_TYPE_P(old_data) == IS_INDIRECT) { - old_data = Z_INDIRECT_P(old_data); + { + zend_property_info *existing_propinfo; + zend_string *new_key, *unmangled; + const char *unmangled_class = NULL; + const char *unmangled_prop; + size_t unmangled_prop_len; + + if (UNEXPECTED(zend_unmangle_property_name_ex(Z_STR(key), &unmangled_class, &unmangled_prop, &unmangled_prop_len) == FAILURE)) { + zval_dtor(&key); + return 0; + } + + unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0); + if (Z_TYPE_P(rval) == IS_OBJECT + && ((existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled)) != NULL) + && (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) { + if (existing_propinfo->flags & ZEND_ACC_PROTECTED) { + new_key = zend_mangle_property_name( + "*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS); + zend_string_release(unmangled); + } else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) { + if (unmangled_class != NULL && strcmp(unmangled_class, "*") != 0) { + new_key = zend_mangle_property_name( + unmangled_class, strlen(unmangled_class), + ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), + Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS); + } else { + new_key = zend_mangle_property_name( + ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name), + ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), + Z_OBJCE_P(rval)->type & ZEND_INTERNAL_CLASS); + } + zend_string_release(unmangled); + } else { + ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC); + new_key = unmangled; + } + zend_string_release(Z_STR(key)); + Z_STR(key) = new_key; + } else { + zend_string_release(unmangled); + } + + if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) { + if (Z_TYPE_P(old_data) == IS_INDIRECT) { + old_data = Z_INDIRECT_P(old_data); + } + var_push_dtor(var_hash, old_data); + data = zend_hash_update_ind(ht, Z_STR(key), &d); + } else { + data = zend_hash_add_new(ht, Z_STR(key), &d); } - var_push_dtor(var_hash, old_data); - data = zend_hash_update_ind(ht, Z_STR(key), &d); - } else { - data = zend_hash_add_new(ht, Z_STR(key), &d); } } else if (Z_TYPE(key) == IS_LONG) { /* object properties should include no integers */

« previous php.cvs (#98482) next »