Skip to content

Commit 75991cf

Browse files
committed
Merge branch 'php7' of github.com:msgpack/msgpack-php into php7
2 parents 274582b + 7a5bdb1 commit 75991cf

File tree

3 files changed

+154
-2
lines changed

3 files changed

+154
-2
lines changed

msgpack.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,14 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) /* {{{ */ {
168168
mp.user.var_hash = &var_hash;
169169

170170
ret = template_execute(&mp, val, vallen, &off);
171+
if (Z_TYPE_P(mp.user.retval) == IS_REFERENCE) {
172+
ZVAL_DEREF(mp.user.retval);
173+
}
171174

172175
if (ret == MSGPACK_UNPACK_EXTRA_BYTES || ret == MSGPACK_UNPACK_SUCCESS) {
173176
msgpack_unserialize_var_destroy(&var_hash, 0);
174177

175-
ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(&tmp), key_str, value) {
178+
ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(mp.user.retval), key_str, value) {
176179
if (key_str) {
177180
php_set_session_var(key_str, value, NULL);
178181
php_add_session_var(key_str);

msgpack_unpack.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,11 @@ static zend_class_entry* msgpack_unserialize_class(zval **container, zend_string
178178
zend_class_entry *ce;
179179
int func_call_status;
180180
zend_bool incomplete_class = 0;
181-
zval user_func, retval, args[1], *container_val;
181+
zval user_func, retval, args[1], *container_val, container_tmp, *val;
182+
zend_string *str_key;
182183

183184
container_val = Z_ISREF_P(*container) ? Z_REFVAL_P(*container) : *container;
185+
ZVAL_UNDEF(&container_tmp);
184186

185187
do {
186188
/* Try to find class directly */
@@ -229,7 +231,22 @@ static zend_class_entry* msgpack_unserialize_class(zval **container, zend_string
229231
}
230232

231233
if (init_class || incomplete_class) {
234+
if (Z_TYPE_P(container_val) == IS_ARRAY) {
235+
ZVAL_COPY_VALUE(&container_tmp, container_val);
236+
}
232237
object_init_ex(container_val, ce);
238+
239+
if (Z_TYPE(container_tmp) != IS_UNDEF) {
240+
ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(&container_tmp), str_key, val) {
241+
const char *class_name, *prop_name;
242+
size_t prop_len;
243+
244+
zend_unmangle_property_name_ex(str_key, &class_name, &prop_name, &prop_len);
245+
zend_update_property(Z_OBJCE_P(container_val), container_val, prop_name, prop_len, val);
246+
} ZEND_HASH_FOREACH_END();
247+
zval_dtor(&container_tmp);
248+
}
249+
233250
}
234251

235252
/* store incomplete class name */

tests/139.phpt

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
--TEST--
2+
Null byte key position while unpacking objects
3+
--SKIPIF--
4+
<?php
5+
if (version_compare(PHP_VERSION, '5.2.0') < 0) {
6+
echo "skip tests in PHP 5.2 or newer";
7+
}
8+
--FILE--
9+
<?php
10+
if(!extension_loaded('msgpack'))
11+
{
12+
dl('msgpack.' . PHP_SHLIB_SUFFIX);
13+
}
14+
15+
function test($type, $array)
16+
{
17+
$stdClass = hex2bin('c0a8737464436c617373'); // "\0" => 'stdClass'
18+
$placeholder = hex2bin('a178a178'); // 'x' => 'x'
19+
20+
$serialized = msgpack_pack($array);
21+
$serialized = str_replace($placeholder, $stdClass, $serialized);
22+
$unserialized = msgpack_unpack($serialized);
23+
24+
var_dump($unserialized);
25+
unset($array['x']);
26+
27+
echo $unserialized == (object) $array ? 'OK' : 'ERROR', PHP_EOL;
28+
}
29+
30+
$array = array('x' => 'x', 'foo' => 1);
31+
test('single property, key at the beginning', $array);
32+
33+
$array = array('foo' => 1, 'x' => 'x');
34+
test('single property, key at the end', $array);
35+
36+
$array = array('x' => 'x', 'foo' => 1, 'bar' => 2);
37+
test('multiple properties, key at the beginning', $array);
38+
39+
$array = array('foo' => 1, 'x' => 'x', 'bar' => 2);
40+
test('multiple properties, key in the middle', $array);
41+
42+
$array = array('foo' => 1, 'bar' => 2, 'x' => 'x');
43+
test('multiple properties, key at the end', $array);
44+
45+
$array = array('null' => null, 'x' => 'x');
46+
test('null, key at the end', $array);
47+
48+
$array = array('int' => 1, 'x' => 'x');
49+
test('int, key at the end', $array);
50+
51+
$array = array('float' => 4.2, 'x' => 'x');
52+
test('float, key at the end', $array);
53+
54+
$array = array('string' => 'str', 'x' => 'x');
55+
test('string, key at the end', $array);
56+
57+
$array = array('array' => array(42), 'x' => 'x');
58+
test('array, key at the end', $array);
59+
60+
class Foo { public $a = null; }
61+
$obj = new Foo();
62+
$array = array('object' => $obj, 'x' => 'x');
63+
test('object, key at the end', $array);
64+
65+
--EXPECTF--
66+
object(stdClass)#%d (1) {
67+
["foo"]=>
68+
int(1)
69+
}
70+
OK
71+
object(stdClass)#%d (1) {
72+
["foo"]=>
73+
int(1)
74+
}
75+
OK
76+
object(stdClass)#%d (2) {
77+
["foo"]=>
78+
int(1)
79+
["bar"]=>
80+
int(2)
81+
}
82+
OK
83+
object(stdClass)#%d (2) {
84+
["foo"]=>
85+
int(1)
86+
["bar"]=>
87+
int(2)
88+
}
89+
OK
90+
object(stdClass)#%d (2) {
91+
["foo"]=>
92+
int(1)
93+
["bar"]=>
94+
int(2)
95+
}
96+
OK
97+
object(stdClass)#%d (1) {
98+
["null"]=>
99+
NULL
100+
}
101+
OK
102+
object(stdClass)#%d (1) {
103+
["int"]=>
104+
int(1)
105+
}
106+
OK
107+
object(stdClass)#%d (1) {
108+
["float"]=>
109+
float(4.2)
110+
}
111+
OK
112+
object(stdClass)#%d (1) {
113+
["string"]=>
114+
string(3) "str"
115+
}
116+
OK
117+
object(stdClass)#%d (1) {
118+
["array"]=>
119+
array(1) {
120+
[0]=>
121+
int(42)
122+
}
123+
}
124+
OK
125+
object(stdClass)#%d (1) {
126+
["object"]=>
127+
object(Foo)#%d (1) {
128+
["a"]=>
129+
NULL
130+
}
131+
}
132+
OK

0 commit comments

Comments
 (0)