Skip to content

Commit f4d2cec

Browse files
Make MessagePack and MessagePackUnpacker not serializable
serialize() lost their options and the buffer of unpackers, and unserialize() created objects without them. Both now throw, and so does msgpack_pack(): from PHP 8.1 on through the ZEND_ACC_NOT_SERIALIZABLE flag, which msgpack_pack() already honors, and before through the zend_class_(un)serialize_deny handlers.
1 parent 4a68908 commit f4d2cec

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

‎msgpack_class.c‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "php.h"
2+
#include "zend_interfaces.h"
23

34
#include "php_msgpack.h"
45
#include "msgpack_pack.h"
@@ -515,6 +516,12 @@ void msgpack_init_class() /* {{{ */ {
515516
INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_base_methods);
516517
msgpack_ce = zend_register_internal_class(&ce);
517518
msgpack_ce->create_object = php_msgpack_base_new;
519+
#if PHP_VERSION_ID >= 80100
520+
msgpack_ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
521+
#else
522+
msgpack_ce->serialize = zend_class_serialize_deny;
523+
msgpack_ce->unserialize = zend_class_unserialize_deny;
524+
#endif
518525
memcpy(&msgpack_handlers, zend_get_std_object_handlers(),sizeof msgpack_handlers);
519526
msgpack_handlers.offset = offsetof(php_msgpack_base_t, object);
520527
msgpack_handlers.free_obj = php_msgpack_base_free;
@@ -527,6 +534,12 @@ void msgpack_init_class() /* {{{ */ {
527534
INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods);
528535
msgpack_unpacker_ce = zend_register_internal_class(&ce);
529536
msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new;
537+
#if PHP_VERSION_ID >= 80100
538+
msgpack_unpacker_ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE;
539+
#else
540+
msgpack_unpacker_ce->serialize = zend_class_serialize_deny;
541+
msgpack_unpacker_ce->unserialize = zend_class_unserialize_deny;
542+
#endif
530543
memcpy(&msgpack_unpacker_handlers, zend_get_std_object_handlers(),sizeof msgpack_unpacker_handlers);
531544
msgpack_unpacker_handlers.offset = offsetof(php_msgpack_unpacker_t, object);
532545
msgpack_unpacker_handlers.free_obj = php_msgpack_unpacker_free;

‎tests/144.phpt‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
MessagePack and MessagePackUnpacker cannot be serialized
3+
--FILE--
4+
<?php
5+
if(!extension_loaded('msgpack')) {
6+
dl('msgpack.' . PHP_SHLIB_SUFFIX);
7+
}
8+
9+
foreach ([new MessagePack(), new MessagePackUnpacker()] as $object) {
10+
try {
11+
serialize($object);
12+
} catch (Exception $e) {
13+
echo $e->getMessage(), PHP_EOL;
14+
}
15+
}
16+
17+
// Before PHP 8.1, only the C: format reaches the handler that throws
18+
$format = PHP_VERSION_ID < 80100 ? 'C' : 'O';
19+
20+
foreach (['MessagePack', 'MessagePackUnpacker'] as $class) {
21+
try {
22+
unserialize($format . ':' . strlen($class) . ':"' . $class . '":0:{}');
23+
} catch (Exception $e) {
24+
echo $e->getMessage(), PHP_EOL;
25+
}
26+
}
27+
28+
try {
29+
msgpack_pack(new MessagePack());
30+
} catch (Exception $e) {
31+
echo $e->getMessage(), PHP_EOL;
32+
}
33+
?>
34+
--EXPECT--
35+
Serialization of 'MessagePack' is not allowed
36+
Serialization of 'MessagePackUnpacker' is not allowed
37+
Unserialization of 'MessagePack' is not allowed
38+
Unserialization of 'MessagePackUnpacker' is not allowed
39+
Serialization of 'MessagePack' is not allowed

0 commit comments

Comments
 (0)