Skip to content

Commit b6e1202

Browse files
committed
fix #186: segmentation fault when unserializing nonexistent enum case
1 parent e0a6616 commit b6e1202

5 files changed

Lines changed: 127 additions & 0 deletions

File tree

‎msgpack_unpack.c‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,40 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
712712
return 0;
713713
}
714714

715+
/* found Enum does not contain specified case */
716+
zend_class_constant *constant_ptr = zend_hash_find_ptr(
717+
&ce->constants_table,
718+
Z_STR_P(val));
719+
if (constant_ptr == NULL) {
720+
MSGPACK_WARNING(
721+
"[msgpack] (%s) Enum case %s does not exist in Enum %s",
722+
__FUNCTION__, Z_STRVAL_P(val), ZSTR_VAL(ce->name));
723+
724+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
725+
return 0;
726+
}
727+
728+
/* found Enum property is not a case but a constant */
729+
zval *constant = &constant_ptr->value;
730+
if (Z_TYPE_P(constant) == IS_OBJECT) {
731+
zend_object *obj = Z_OBJ_P(constant);
732+
if (!instanceof_function(obj->ce, ce)) {
733+
MSGPACK_WARNING(
734+
"[msgpack] (%s) %s::%s is not an Enum case but a constant",
735+
__FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val));
736+
737+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
738+
return 0;
739+
}
740+
} else {
741+
MSGPACK_WARNING(
742+
"[msgpack] (%s) %s::%s is not an Enum case but a constant",
743+
__FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val));
744+
745+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
746+
return 0;
747+
}
748+
715749
zend_object *enum_instance = zend_enum_get_case(ce, Z_STR_P(val));
716750
ZVAL_OBJ_COPY(*container, enum_instance);
717751
#endif

‎tests/issue186.1.phpt‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Issue #182 (unknown enum case)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("msgpack")) {
6+
exit('skip because msgpack extension is missing');
7+
}
8+
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
9+
exit('skip Enum tests in PHP older than 8.1.0');
10+
}
11+
?>
12+
--FILE--
13+
Test
14+
<?php
15+
enum TestEnum
16+
{
17+
case A;
18+
}
19+
20+
$data = file_get_contents(__DIR__.'/issue186.ser.txt');
21+
$unserilized = msgpack_unserialize($data);
22+
?>
23+
OK
24+
--EXPECTF--
25+
Test
26+
27+
Warning: [msgpack] (msgpack_unserialize_map_item) Enum case B does not exist in Enum TestEnum in %s/issue186.1.php on line 9
28+
OK

‎tests/issue186.2.phpt‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Issue #182 (unknown enum case)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("msgpack")) {
6+
exit('skip because msgpack extension is missing');
7+
}
8+
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
9+
exit('skip Enum tests in PHP older than 8.1.0');
10+
}
11+
?>
12+
--FILE--
13+
Test
14+
<?php
15+
enum TestEnum
16+
{
17+
case A;
18+
19+
public const B = 42;
20+
}
21+
22+
$data = file_get_contents(__DIR__.'/issue186.ser.txt');
23+
$unserilized = msgpack_unserialize($data);
24+
?>
25+
OK
26+
--EXPECTF--
27+
Test
28+
29+
Warning: [msgpack] (msgpack_unserialize_map_item) TestEnum::B is not an Enum case but a constant in %s/issue186.2.php on line 11
30+
OK

‎tests/issue186.3.phpt‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
Issue #182 (unknown enum case)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("msgpack")) {
6+
exit('skip because msgpack extension is missing');
7+
}
8+
if (version_compare(PHP_VERSION, '8.1.0', '<')) {
9+
exit('skip Enum tests in PHP older than 8.1.0');
10+
}
11+
?>
12+
--FILE--
13+
Test
14+
<?php
15+
enum AnotherEnum {
16+
case C;
17+
}
18+
19+
enum TestEnum
20+
{
21+
case A;
22+
23+
public const B = AnotherEnum::C;
24+
}
25+
26+
$data = file_get_contents(__DIR__.'/issue186.ser.txt');
27+
$unserilized = msgpack_unserialize($data);
28+
?>
29+
OK
30+
--EXPECTF--
31+
Test
32+
33+
Warning: [msgpack] (msgpack_unserialize_map_item) TestEnum::B is not an Enum case but a constant in %s/issue186.3.php on line 15
34+
OK

‎tests/issue186.ser.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
���TestEnum�B

0 commit comments

Comments
 (0)