diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2018-11-23 16:32:33 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2018-11-23 16:32:33 +0100 |
commit | 115ee49b0be12e3df7d2c7027609fbe1a1297e42 (patch) | |
tree | 6351c4b6b9c5e09c8a699613237afae1fa908975 /ext | |
parent | f2de4d185d9c4a2bb8d7e0a617c5a91496ea1ed9 (diff) | |
download | php-git-115ee49b0be12e3df7d2c7027609fbe1a1297e42.tar.gz |
Fix #77177: Serializing or unserializing COM objects crashes
Firstly, we avoid returning NULL from the get_property handler, but
instead return an empty HashTable, which already prevents the crashes.
Secondly, since (de-)serialization obviously makes no sense for COM,
DOTNET and VARIANT objects (at least with the current implementation),
we prohibit it right away.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/com_dotnet/com_extension.c | 9 | ||||
-rw-r--r-- | ext/com_dotnet/com_handlers.c | 4 | ||||
-rw-r--r-- | ext/com_dotnet/php_com_dotnet_internal.h | 2 | ||||
-rw-r--r-- | ext/com_dotnet/tests/bug77177.phpt | 57 |
4 files changed, 71 insertions, 1 deletions
diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c index 3b26cf1eb8..859738647d 100644 --- a/ext/com_dotnet/com_extension.c +++ b/ext/com_dotnet/com_extension.c @@ -30,6 +30,7 @@ #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" #include "Zend/zend_exceptions.h" +#include "Zend/zend_interfaces.h" ZEND_DECLARE_MODULE_GLOBALS(com_dotnet) static PHP_GINIT_FUNCTION(com_dotnet); @@ -354,6 +355,8 @@ PHP_MINIT_FUNCTION(com_dotnet) { zend_class_entry ce, *tmp; + zend_hash_init(&com_dotnet_object_properties, 0, NULL, NULL, 0); + php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU); php_com_persist_minit(INIT_FUNC_ARGS_PASSTHRU); @@ -372,11 +375,15 @@ PHP_MINIT_FUNCTION(com_dotnet) ce.create_object = php_com_object_new; php_com_variant_class_entry = zend_register_internal_class(&ce); php_com_variant_class_entry->get_iterator = php_com_iter_get; + php_com_variant_class_entry->serialize = zend_class_serialize_deny; + php_com_variant_class_entry->unserialize = zend_class_unserialize_deny; INIT_CLASS_ENTRY(ce, "com", NULL); ce.create_object = php_com_object_new; tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry); tmp->get_iterator = php_com_iter_get; + tmp->serialize = zend_class_serialize_deny; + tmp->unserialize = zend_class_unserialize_deny; zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 1); @@ -385,6 +392,8 @@ PHP_MINIT_FUNCTION(com_dotnet) ce.create_object = php_com_object_new; tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry); tmp->get_iterator = php_com_iter_get; + tmp->serialize = zend_class_serialize_deny; + tmp->unserialize = zend_class_unserialize_deny; #endif REGISTER_INI_ENTRIES(); diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index fd9cdf22b0..1fc6c04c9a 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -29,6 +29,8 @@ #include "php_com_dotnet_internal.h" #include "Zend/zend_exceptions.h" +const HashTable com_dotnet_object_properties; + static zval *com_property_read(zval *object, zval *member, int type, void **cahce_slot, zval *rv) { php_com_dotnet_object *obj; @@ -231,7 +233,7 @@ static HashTable *com_properties_get(zval *object) * infinite recursion when the hash is displayed via var_dump(). * Perhaps it is best to leave it un-implemented. */ - return NULL; + return &com_dotnet_object_properties; } static void function_dtor(zval *zv) diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h index 506a14b542..f6147b2e81 100644 --- a/ext/com_dotnet/php_com_dotnet_internal.h +++ b/ext/com_dotnet/php_com_dotnet_internal.h @@ -31,6 +31,8 @@ #include "zend_ts_hash.h" +extern const HashTable com_dotnet_object_properties; + typedef struct _php_com_dotnet_object { zend_object zo; diff --git a/ext/com_dotnet/tests/bug77177.phpt b/ext/com_dotnet/tests/bug77177.phpt new file mode 100644 index 0000000000..901358248c --- /dev/null +++ b/ext/com_dotnet/tests/bug77177.phpt @@ -0,0 +1,57 @@ +--TEST-- +Bug #77177 (Serializing or unserializing COM objects crashes) +--SKIPIF-- +<?php +if (!extension_loaded('com_dotnet')) die('skip com_dotnet extension not available'); +?> +--FILE-- +<?php +$com = new COM("WScript.Shell"); +$dotnet = new DOTNET("mscorlib", "System.Collections.Stack"); +$variant = new VARIANT; +foreach ([$com, $dotnet, $variant] as $object) { + try { + serialize($object); + } catch (Exception $ex) { + echo "Exception: {$ex->getMessage()}\n"; + } +} + +$strings = ['C:3:"com":0:{}', 'C:6:"dotnet":0:{}', 'C:7:"variant":0:{}']; +foreach ($strings as $string) { + try { + unserialize($string); + } catch (Exception $ex) { + echo "Exception: {$ex->getMessage()}\n"; + } +} + +$strings = ['O:3:"com":0:{}', 'O:6:"dotnet":0:{}', 'O:7:"variant":0:{}']; +foreach ($strings as $string) { + var_dump(unserialize($string)); +} +?> +===DONE=== +--EXPECTF-- +Exception: Serialization of 'com' is not allowed +Exception: Serialization of 'dotnet' is not allowed +Exception: Serialization of 'variant' is not allowed +Exception: Unserialization of 'com' is not allowed +Exception: Unserialization of 'dotnet' is not allowed +Exception: Unserialization of 'variant' is not allowed + +Warning: Erroneous data format for unserializing 'com' in %s on line %d + +Notice: unserialize(): Error at offset 13 of 14 bytes in %s on line %d +bool(false) + +Warning: Erroneous data format for unserializing 'dotnet' in %s on line %d + +Notice: unserialize(): Error at offset 16 of 17 bytes in %s on line %d +bool(false) + +Warning: Erroneous data format for unserializing 'variant' in %s on line %d + +Notice: unserialize(): Error at offset 17 of 18 bytes in %s on line %d +bool(false) +===DONE=== |