summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2018-09-29 14:47:57 +0200
committerNikita Popov <nikita.ppv@gmail.com>2018-09-29 14:47:57 +0200
commit96da1fe8a906da8d2927f57ff94ed25a8e6ea411 (patch)
tree128f27c6feb9fc329c0277646cd6daee28a9cb0e
parent2ae2e820bee97fc9b50ce5d9462e1da2e72e6417 (diff)
downloadphp-git-96da1fe8a906da8d2927f57ff94ed25a8e6ea411.tar.gz
Fixed bug #76737
Explicitly prohibit serialization and unserialization of reflection objects.
-rw-r--r--NEWS4
-rw-r--r--UPGRADING6
-rw-r--r--ext/reflection/php_reflection.c32
-rw-r--r--ext/reflection/tests/bug76737.phpt33
4 files changed, 62 insertions, 13 deletions
diff --git a/NEWS b/NEWS
index 49d5716d87..0b4764b7e3 100644
--- a/NEWS
+++ b/NEWS
@@ -21,4 +21,8 @@ PHP NEWS
. Fixed bug #74764 (Bindto IPv6 works with file_get_contents but fails with
stream_socket_client). (Ville Hukkamäki)
+- Reflection:
+ . Fixed bug #76737 (Unserialized reflection objects are broken, they
+ shouldn't be serializable). (Nikita)
+
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/UPGRADING b/UPGRADING
index 0bb09c6bc4..ccea43b31f 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -23,6 +23,12 @@ PHP 7.4 UPGRADE NOTES
. The default parameter value of idn_to_ascii() and idn_to_utf8() is now
INTL_IDNA_VARIANT_UTS46 instead of the deprecated INTL_IDNA_VARIANT_2003.
+- Reflection:
+ . Reflection objects will now generate an exception if an attempt is made
+ to serialize them. Serialization for reflection objects was never
+ supported and resulted in corrupted reflection objects. It has been
+ explicitly prohibited now.
+
========================================
2. New Features
========================================
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index af15675a65..14cde3de05 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -6598,6 +6598,12 @@ static void _reflection_write_property(zval *object, zval *member, zval *value,
}
/* }}} */
+static void reflection_init_class_handlers(zend_class_entry *ce) {
+ ce->create_object = reflection_objects_new;
+ ce->serialize = zend_class_serialize_deny;
+ ce->unserialize = zend_class_unserialize_deny;
+}
+
PHP_MINIT_FUNCTION(reflection) /* {{{ */
{
zend_class_entry _reflection_entry;
@@ -6619,38 +6625,38 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
reflector_ptr = zend_register_internal_interface(&_reflection_entry);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", reflection_generator_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
@@ -6663,7 +6669,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
@@ -6673,18 +6679,18 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
@@ -6696,13 +6702,13 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
- _reflection_entry.create_object = reflection_objects_new;
+ reflection_init_class_handlers(&_reflection_entry);
reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
diff --git a/ext/reflection/tests/bug76737.phpt b/ext/reflection/tests/bug76737.phpt
new file mode 100644
index 0000000000..716b40e76a
--- /dev/null
+++ b/ext/reflection/tests/bug76737.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #76737: Unserialized reflection objects are broken, they shouldn't be serializable
+--FILE--
+<?php
+
+try {
+ $r = new ReflectionClass('stdClass');
+ var_dump(serialize($r));
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ $s = 'C:15:"ReflectionClass":0:{}';
+ var_dump(unserialize($s));
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ $s = 'O:15:"ReflectionClass":0:{}';
+ var_dump(unserialize($s));
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECTF--
+Serialization of 'ReflectionClass' is not allowed
+Unserialization of 'ReflectionClass' is not allowed
+
+Warning: Erroneous data format for unserializing 'ReflectionClass' in %s on line %d
+
+Notice: unserialize(): Error at offset 26 of 27 bytes in %s on line %d
+bool(false)