diff --git a/msgpack_pack.c b/msgpack_pack.c index 57887c1..85d2cd4 100644 --- a/msgpack_pack.c +++ b/msgpack_pack.c @@ -343,7 +343,7 @@ static inline void msgpack_serialize_array(smart_str *buf, zval *val, HashTable zval *data_noref, *data = zend_hash_index_find(ht, i); if (!data) { - MSGPACK_WARNING("[msgpack (%s) array index %u is not set", __FUNCTION__, i); + MSGPACK_WARNING("[msgpack] (%s) array index %u is not set", __FUNCTION__, i); msgpack_pack_nil(buf); continue; } diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 9b3cc3b..30e1d9e 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -692,8 +692,28 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container, __FUNCTION__, Z_STRVAL_P(key)); #else ce = msgpack_unserialize_class(container, Z_STR_P(key), 0); + /* Enums are not allowed to implement Serializable nor __unserialize */ + if (ce == NULL || ce == PHP_IC_ENTRY) { + MSGPACK_WARNING( + "[msgpack] (%s) Enum definition %s could not be loaded", + __FUNCTION__, Z_STRVAL_P(key)); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + return 0; + } + + /* found class is not an Enum but a normal Class */ + if (!(ce->ce_flags & ZEND_ACC_ENUM)) { + MSGPACK_WARNING( + "[msgpack] (%s) Class %s is expected to be an Enum", + __FUNCTION__, ZSTR_VAL(ce->name)); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + return 0; + } + zend_object *enum_instance = zend_enum_get_case(ce, Z_STR_P(val)); - ZVAL_OBJ(*container, enum_instance); + ZVAL_OBJ_COPY(*container, enum_instance); #endif MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); return 0; diff --git a/tests/enum002.phpt b/tests/enum002.phpt new file mode 100644 index 0000000..56895d7 --- /dev/null +++ b/tests/enum002.phpt @@ -0,0 +1,27 @@ +--TEST-- +Enums +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: [msgpack] (msgpack_unserialize_map_item) Enum definition test\TestEnum could not be loaded in %senum002.php on line 2 +array(1) { + ["enum"]=> + object(__PHP_Incomplete_Class)#1 (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(13) "test\TestEnum" + } +} +DONE diff --git a/tests/enum002.ser.txt b/tests/enum002.ser.txt new file mode 100644 index 0000000..7229336 --- /dev/null +++ b/tests/enum002.ser.txt @@ -0,0 +1 @@ +¤enum‚À­test\TestEnumĦA \ No newline at end of file diff --git a/tests/enum003.phpt b/tests/enum003.phpt new file mode 100644 index 0000000..3ffe176 --- /dev/null +++ b/tests/enum003.phpt @@ -0,0 +1,33 @@ +--TEST-- +Enums +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: [msgpack] (msgpack_unserialize_map_item) Class test\TestEnum is expected to be an Enum in %senum003.php on line 8 +array(1) { + ["enum"]=> + NULL +} +DONE diff --git a/tests/issue181.phpt b/tests/issue181.phpt new file mode 100644 index 0000000..a3d844f --- /dev/null +++ b/tests/issue181.phpt @@ -0,0 +1,43 @@ +--TEST-- +Issue #181 (zend_mm_heap corrupted when serializing/unserializing Enum) +--SKIPIF-- + +--FILE-- +Test + TestEnum::EITHER, + 'other' => TestEnum::OTHER, +]; + +for ($i = 0; $i < 10; $i++) { + $packed = msgpack_pack($original); + $unpacked = msgpack_unpack($packed); + if ($unpacked->either !== TestEnum::EITHER) { + echo 'either mismatch'; + } + if ($original->other !== TestEnum::OTHER) { + echo 'other mismatch'; + } + unset($packed); + unset($unpacked); +} +?> +OK +--EXPECT-- +Test +OK