summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2018-11-23 16:32:33 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2018-11-23 16:32:33 +0100
commit115ee49b0be12e3df7d2c7027609fbe1a1297e42 (patch)
tree6351c4b6b9c5e09c8a699613237afae1fa908975 /ext
parentf2de4d185d9c4a2bb8d7e0a617c5a91496ea1ed9 (diff)
downloadphp-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.c9
-rw-r--r--ext/com_dotnet/com_handlers.c4
-rw-r--r--ext/com_dotnet/php_com_dotnet_internal.h2
-rw-r--r--ext/com_dotnet/tests/bug77177.phpt57
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===