Skip to content

Commit d0ca4ee

Browse files
authored
Merge pull request #187 from cracksalad/master
fix #186: segmentation fault when unserializing nonexistent enum case
2 parents 4e72cb3 + b6e1202 commit d0ca4ee

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
@@ -722,6 +722,40 @@ int msgpack_unserialize_map_item(msgpack_unpack_data *unpack, zval **container,
722722
return 0;
723723
}
724724

725+
/* found Enum does not contain specified case */
726+
zend_class_constant *constant_ptr = zend_hash_find_ptr(
727+
&ce->constants_table,
728+
Z_STR_P(val));
729+
if (constant_ptr == NULL) {
730+
MSGPACK_WARNING(
731+
"[msgpack] (%s) Enum case %s does not exist in Enum %s",
732+
__FUNCTION__, Z_STRVAL_P(val), ZSTR_VAL(ce->name));
733+
734+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
735+
return 0;
736+
}
737+
738+
/* found Enum property is not a case but a constant */
739+
zval *constant = &constant_ptr->value;
740+
if (Z_TYPE_P(constant) == IS_OBJECT) {
741+
zend_object *obj = Z_OBJ_P(constant);
742+
if (!instanceof_function(obj->ce, ce)) {
743+
MSGPACK_WARNING(
744+
"[msgpack] (%s) %s::%s is not an Enum case but a constant",
745+
__FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val));
746+
747+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
748+
return 0;
749+
}
750+
} else {
751+
MSGPACK_WARNING(
752+
"[msgpack] (%s) %s::%s is not an Enum case but a constant",
753+
__FUNCTION__, ZSTR_VAL(ce->name), Z_STRVAL_P(val));
754+
755+
MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val);
756+
return 0;
757+
}
758+
725759
zend_object *enum_instance = zend_enum_get_case(ce, Z_STR_P(val));
726760
ZVAL_OBJ_COPY(*container, enum_instance);
727761
#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)