From b6e1202d782cac03ff00f3ee70bd58d11abc39b4 Mon Sep 17 00:00:00 2001 From: Andreas Wahlen Date: Wed, 26 Aug 2026 15:42:37 +0200 Subject: [PATCH] fix #186: segmentation fault when unserializing nonexistent enum case --- msgpack_unpack.c | 34 ++++++++++++++++++++++++++++++++++ tests/issue186.1.phpt | 28 ++++++++++++++++++++++++++++ tests/issue186.2.phpt | 30 ++++++++++++++++++++++++++++++ tests/issue186.3.phpt | 34 ++++++++++++++++++++++++++++++++++ tests/issue186.ser.txt | 1 + 5 files changed, 127 insertions(+) create mode 100644 tests/issue186.1.phpt create mode 100644 tests/issue186.2.phpt create mode 100644 tests/issue186.3.phpt create mode 100644 tests/issue186.ser.txt diff --git a/msgpack_unpack.c b/msgpack_unpack.c index 88387e5..644ee94 100644 --- a/msgpack_unpack.c +++ b/msgpack_unpack.c @@ -712,6 +712,40 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container, return 0; } + /* found Enum does not contain specified case */ + zend_class_constant *constant_ptr = zend_hash_find_ptr( + &ce->constants_table, + Z_STR_P(val)); + if (constant_ptr == NULL) { + MSGPACK_WARNING( + "[msgpack] (%s) Enum case %s does not exist in Enum %s", + __FUNCTION__, Z_STRVAL_P(val), ZSTR_VAL(ce->name)); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + return 0; + } + + /* found Enum property is not a case but a constant */ + zval *constant = &constant_ptr->value; + if (Z_TYPE_P(constant) == IS_OBJECT) { + zend_object *obj = Z_OBJ_P(constant); + if (!instanceof_function(obj->ce, ce)) { + MSGPACK_WARNING( + "[msgpack] (%s) %s::%s is not an Enum case but a constant", + __FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val)); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + return 0; + } + } else { + MSGPACK_WARNING( + "[msgpack] (%s) %s::%s is not an Enum case but a constant", + __FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val)); + + 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_COPY(*container, enum_instance); #endif diff --git a/tests/issue186.1.phpt b/tests/issue186.1.phpt new file mode 100644 index 0000000..d93f1dd --- /dev/null +++ b/tests/issue186.1.phpt @@ -0,0 +1,28 @@ +--TEST-- +Issue #182 (unknown enum case) +--SKIPIF-- + +--FILE-- +Test + +OK +--EXPECTF-- +Test + +Warning: [msgpack] (msgpack_unserialize_map_item) Enum case B does not exist in Enum TestEnum in %s/issue186.1.php on line 9 +OK diff --git a/tests/issue186.2.phpt b/tests/issue186.2.phpt new file mode 100644 index 0000000..d5723de --- /dev/null +++ b/tests/issue186.2.phpt @@ -0,0 +1,30 @@ +--TEST-- +Issue #182 (unknown enum case) +--SKIPIF-- + +--FILE-- +Test + +OK +--EXPECTF-- +Test + +Warning: [msgpack] (msgpack_unserialize_map_item) TestEnum::B is not an Enum case but a constant in %s/issue186.2.php on line 11 +OK diff --git a/tests/issue186.3.phpt b/tests/issue186.3.phpt new file mode 100644 index 0000000..8b44cce --- /dev/null +++ b/tests/issue186.3.phpt @@ -0,0 +1,34 @@ +--TEST-- +Issue #182 (unknown enum case) +--SKIPIF-- + +--FILE-- +Test + +OK +--EXPECTF-- +Test + +Warning: [msgpack] (msgpack_unserialize_map_item) TestEnum::B is not an Enum case but a constant in %s/issue186.3.php on line 15 +OK diff --git a/tests/issue186.ser.txt b/tests/issue186.ser.txt new file mode 100644 index 0000000..130b76a --- /dev/null +++ b/tests/issue186.ser.txt @@ -0,0 +1 @@ +‚À¨TestEnumĦB \ No newline at end of file