Bug #77177 [Com]: serializing or unserializing a com() will cause a crash

From: Date: Tue, 20 Nov 2018 00:53:26 +0000
Subject: Bug #77177 [Com]: serializing or unserializing a com() will cause a crash
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-218058@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=77177&edit=1

 ID:                 77177
 Comment by:         php at zsxsoft dot com
 Reported by:        php at zsxsoft dot com
 Summary:            serializing or unserializing a com() will cause a
                     crash
 Status:             Verified
 Type:               Bug
 Package:            Reproducible crash
 Operating System:   Windows
 PHP Version:        PHP 7.1.24
 Block user comment: N
 Private report:     N

 New Comment:

After fuzzing, I found unserialize those classes can crash php: 
- variant
- com
- dotnet


unserialize('O:7:"variant":0:{}');
unserialize('O:3:"com":0:{}');
unserialize('O:6:"dotnet":0:{}');


Previous Comments:
------------------------------------------------------------------------
[2018-11-20 00:40:33] php at zsxsoft dot com

Unserialize a com will cause a crash too.

------------------------------------------------------------------------
[2018-11-20 00:37:57] php at zsxsoft dot com

Also, unserialize a com will cause a crash too.

I reviewed the git blame and found this bug can effect from PHP 5.0RC1RC1 to branch master: https://github.com/php/php-src/blob/6df5d5ba202b531de6bb563e2462e046d701e8d6/ext/com_dotnet/com_handlers.c#L264.

Effected code
---------
ext/standard/var_unserializer.c
static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)

ht = Z_OBJPROP_P(rval);
if (elements >= (zend_long)(HT_MAX_SIZE - zend_hash_num_elements(ht))) {
  return 0;
}


Code
---------
<?php
 $c = unserialize('O:3:"com":0:{}');

------------------------------------------------------------------------
[2018-11-19 18:33:16] cmb@php.net

This also happens with older PHP versions.

Is an get_properties handler supposed to ever return NULL?

------------------------------------------------------------------------
[2018-11-19 16:38:20] php at zsxsoft dot com

Description:
------------
When try to serialize a class, serialize will try to get all properties of
the class by zend_get_properties_for. Then it will get the count of the properties by
zend_array_count without checking nullptr. 

com and com_safearray_proxy will always returns NULL in
com_properties_get so it will crash on zend_array_count.

Affect code
------------------------
ext/standard/var.c

static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_data_t var_hash) /*
{{{ */
[...]
incomplete_class = php_var_serialize_class_name(buf, struc);
myht = zend_get_properties_for(struc, ZEND_PROP_PURPOSE_SERIALIZE);
> i = zend_array_count(myht); // Crash here because myht == NULL
if (i > 0 && incomplete_class) {
  --i;
}


ext/com_dotnet/com_handlers.c

static HashTable *com_properties_get(zval *object)
{
	/* TODO: use type-info to get all the names and values ?
	 * DANGER: if we do that, there is a strong possibility for
	 * infinite recursion when the hash is displayed via var_dump().
	 * Perhaps it is best to leave it un-implemented.
	 */
	return NULL;
}



Test script:
---------------
<?php
$a = new COM("WScript.Shell");
serialize($a);

Expected result:
----------------
Nothing happened

Actual result:
--------------
Crash


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=77177&edit=1


Thread (9 messages)

« previous php.bugs (#218058) next »