@@ -29,18 +29,28 @@ typedef struct {
2929 *obj = msgpack_var_push(_unpack->var_hash); \
3030 }
3131
32- #define MSGPACK_UNSERIALIZE_FINISH_ITEM (_unpack , op1 , op2 ) \
33- msgpack_stack_pop(_unpack->var_hash, op1, op2); \
32+ #define MSGPACK_UNSERIALIZE_DEC_DEP (_unpack ) \
3433 _unpack->stack[_unpack->deps-1]--; \
3534 if (_unpack->stack[_unpack->deps-1] <= 0) { \
3635 _unpack->deps--; \
3736 }
3837
38+ #define MSGPACK_UNSERIALIZE_FINISH_ITEM (_unpack , _v1 , _v2 ) \
39+ if ((_v2) && MSGPACK_IS_STACK_VALUE((_v2))) { \
40+ msgpack_stack_pop(_unpack->var_hash, (_v2)); \
41+ } \
42+ if ((_v1) && MSGPACK_IS_STACK_VALUE((_v1))) { \
43+ msgpack_stack_pop(_unpack->var_hash, (_v1)); \
44+ } \
45+ MSGPACK_UNSERIALIZE_DEC_DEP(_unpack);
46+
3947#define MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM (_unpack , _key , _val ) \
4048 zval_ptr_dtor(_key); \
4149 zval_ptr_dtor(_val); \
4250 MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack, _key, _val);
4351
52+ #define MSGPACK_IS_STACK_VALUE (_v ) (Z_TYPE_P((_v)) < IS_ARRAY)
53+
4454static zval * msgpack_var_push (msgpack_unserialize_data_t * var_hashx ) /* {{{ */ {
4555 var_entries * var_hash , * prev = NULL ;
4656
@@ -71,6 +81,13 @@ static zval *msgpack_var_push(msgpack_unserialize_data_t *var_hashx) /* {{{ */ {
7181}
7282/* }}} */
7383
84+ static inline void msgpack_var_replace (zval * old , zval * new ) /* {{{ */ {
85+ if (!MSGPACK_IS_STACK_VALUE (old )) {
86+ ZVAL_INDIRECT (old , new );
87+ }
88+ }
89+ /* }}} */
90+
7491static zval * msgpack_var_access (msgpack_unserialize_data_t * var_hashx , long id ) /* {{{ */ {
7592 var_entries * var_hash = var_hashx -> first ;
7693
@@ -84,7 +101,11 @@ static zval *msgpack_var_access(msgpack_unserialize_data_t *var_hashx, long id)
84101 }
85102
86103 if (id > 0 && id < var_hash -> used_slots ) {
87- return & var_hash -> data [id - 1 ];
104+ zval * zv = & var_hash -> data [id - 1 ];
105+ if (UNEXPECTED (Z_TYPE_P (zv ) == IS_INDIRECT )) {
106+ zv = Z_INDIRECT_P (zv );
107+ }
108+ return zv ;
88109 }
89110
90111 return NULL ;
@@ -121,8 +142,7 @@ static zval *msgpack_stack_push(msgpack_unserialize_data_t *var_hashx) /* {{{ */
121142}
122143/* }}} */
123144
124- static void msgpack_stack_pop (msgpack_unserialize_data_t * var_hashx , zval * op1 , zval * op2 ) /* {{{ */ {
125- int32_t i ;
145+ static void msgpack_stack_pop (msgpack_unserialize_data_t * var_hashx , zval * v ) /* {{{ */ {
126146 var_entries * var_hash = var_hashx -> first_dtor ;
127147
128148 while (var_hash && var_hash -> used_slots == VAR_ENTRIES_MAX ) {
@@ -133,20 +153,10 @@ static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, zval *op1,
133153 return ;
134154 }
135155
136- if (op2 && Z_TYPE_P (op2 ) < IS_ARRAY ) {
137- ZEND_ASSERT ((& (var_hash -> data [var_hash -> used_slots - 1 ]) == op2 ));
138- if ((& (var_hash -> data [var_hash -> used_slots - 1 ]) == op2 )) {
139- var_hash -> used_slots -- ;
140- ZVAL_UNDEF (op2 );
141- }
142- }
143-
144- if (op1 && Z_TYPE_P (op1 ) < IS_ARRAY ) {
145- ZEND_ASSERT ((& (var_hash -> data [var_hash -> used_slots - 1 ]) == op1 ));
146- if (& (var_hash -> data [var_hash -> used_slots - 1 ]) == op1 ) {
147- var_hash -> used_slots -- ;
148- ZVAL_UNDEF (op1 );
149- }
156+ ZEND_ASSERT ((& (var_hash -> data [var_hash -> used_slots - 1 ]) == v ));
157+ if ((& (var_hash -> data [var_hash -> used_slots - 1 ]) == v )) {
158+ var_hash -> used_slots -- ;
159+ ZVAL_UNDEF (v );
150160 }
151161
152162 /*
@@ -245,7 +255,7 @@ void msgpack_unserialize_var_destroy(msgpack_unserialize_data_t *var_hashx, zend
245255 while (var_hash ) {
246256 if (err ) {
247257 for (i = var_hash -> used_slots ; i > 0 ; i -- ) {
248- /* TODO: memleaks ? zval_ptr_dtor(&var_hash->data[i - 1]); */
258+ zval_ptr_dtor (& var_hash -> data [i - 1 ]);
249259 }
250260 }
251261 next = var_hash -> next ;
@@ -415,9 +425,14 @@ int msgpack_unserialize_array(msgpack_unserialize_data *unpack, unsigned int cou
415425/* }}} */
416426
417427int msgpack_unserialize_array_item (msgpack_unserialize_data * unpack , zval * * container , zval * obj ) /* {{{ */ {
418- add_next_index_zval ( * container , obj );
428+ zval * nval = zend_hash_next_index_insert ( Z_ARRVAL_P ( * container ) , obj );
419429
420- MSGPACK_UNSERIALIZE_FINISH_ITEM (unpack , obj , NULL );
430+ if (MSGPACK_IS_STACK_VALUE (obj )) {
431+ MSGPACK_UNSERIALIZE_FINISH_ITEM (unpack , obj , NULL );
432+ } else {
433+ msgpack_var_replace (obj , nval );
434+ MSGPACK_UNSERIALIZE_DEC_DEP (unpack );
435+ }
421436
422437 return 0 ;
423438}
@@ -448,6 +463,7 @@ int msgpack_unserialize_map(msgpack_unserialize_data *unpack, unsigned int count
448463
449464int msgpack_unserialize_map_item (msgpack_unserialize_data * unpack , zval * * container , zval * key , zval * val ) /* {{{ */ {
450465 long deps ;
466+ zval * nval ;
451467 zval * container_val ;
452468
453469 if (MSGPACK_G (php_only )) {
@@ -554,7 +570,7 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
554570 if (Z_TYPE_P (container_val ) == IS_OBJECT ) {
555571 switch (Z_TYPE_P (key )) {
556572 case IS_LONG :
557- if (zend_hash_index_update (Z_OBJPROP_P (container_val ), Z_LVAL_P (key ), val ) == NULL ) {
573+ if (( nval = zend_hash_index_update (Z_OBJPROP_P (container_val ), Z_LVAL_P (key ), val ) ) == NULL ) {
558574 zval_ptr_dtor (val );
559575 MSGPACK_WARNING (
560576 "[msgpack] (%s) illegal offset type, skip this decoding" ,
@@ -568,11 +584,12 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
568584
569585 zend_unmangle_property_name_ex (Z_STR_P (key ), & class_name , & prop_name , & prop_len );
570586 zend_update_property (Z_OBJCE_P (container_val ), container_val , prop_name , prop_len , val );
587+ nval = zend_read_property (Z_OBJCE_P (container_val ), container_val , prop_name , prop_len , 0 , NULL );
571588
572589 zval_ptr_dtor (key );
573590 zval_ptr_dtor (val );
574591 } else {
575- if (zend_symtable_update (Z_OBJPROP_P (container_val ), Z_STR_P (key ), val ) == NULL ) {
592+ if (( nval = zend_symtable_update (Z_OBJPROP_P (container_val ), Z_STR_P (key ), val ) ) == NULL ) {
576593 zval_ptr_dtor (val );
577594 MSGPACK_WARNING (
578595 "[msgpack] (%s) illegal offset type, skip this decoding" ,
@@ -585,15 +602,15 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
585602 MSGPACK_WARNING ("[msgpack] (%s) illegal key type" , __FUNCTION__ );
586603
587604 if (MSGPACK_G (illegal_key_insert )) {
588- if ((zend_hash_next_index_insert (Z_OBJPROP_P (container_val ), key )) == NULL ) {
605+ if ((nval = zend_hash_next_index_insert (Z_OBJPROP_P (container_val ), key )) == NULL ) {
589606 zval_ptr_dtor (key );
590607 }
591- if ((zend_hash_next_index_insert (Z_OBJPROP_P (container_val ), val )) == NULL ) {
608+ if ((nval = zend_hash_next_index_insert (Z_OBJPROP_P (container_val ), val )) == NULL ) {
592609 zval_ptr_dtor (val );
593610 }
594611 } else {
595612 zend_string * skey = zval_get_string (key );
596- if ((zend_symtable_update (Z_OBJPROP_P (container_val ), skey , val )) == NULL ) {
613+ if ((nval = zend_symtable_update (Z_OBJPROP_P (container_val ), skey , val )) == NULL ) {
597614 zval_ptr_dtor (val );
598615 }
599616 zend_string_release (skey );
@@ -606,15 +623,15 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
606623 }
607624 switch (Z_TYPE_P (key )) {
608625 case IS_LONG :
609- if (zend_hash_index_update (Z_ARRVAL_P (container_val ), Z_LVAL_P (key ), val ) == NULL ) {
626+ if (( nval = zend_hash_index_update (Z_ARRVAL_P (container_val ), Z_LVAL_P (key ), val ) ) == NULL ) {
610627 zval_ptr_dtor (val );
611628 MSGPACK_WARNING (
612629 "[msgpack] (%s) illegal offset type, skip this decoding" ,
613630 __FUNCTION__ );
614631 }
615632 break ;
616633 case IS_STRING :
617- if (zend_symtable_update (Z_ARRVAL_P (container_val ), Z_STR_P (key ), val ) == NULL ) {
634+ if (( nval = zend_symtable_update (Z_ARRVAL_P (container_val ), Z_STR_P (key ), val ) ) == NULL ) {
618635 zval_ptr_dtor (val );
619636 MSGPACK_WARNING (
620637 "[msgpack] (%s) illegal offset type, skip this decoding" ,
@@ -626,15 +643,15 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
626643 MSGPACK_WARNING ("[msgpack] (%s) illegal key type" , __FUNCTION__ );
627644
628645 if (MSGPACK_G (illegal_key_insert )) {
629- if (zend_hash_next_index_insert (Z_ARRVAL_P (container_val ), key ) == NULL ) {
646+ if (( nval = zend_hash_next_index_insert (Z_ARRVAL_P (container_val ), key ) ) == NULL ) {
630647 zval_ptr_dtor (key );
631648 }
632- if (zend_hash_next_index_insert (Z_ARRVAL_P (container_val ), val ) == NULL ) {
649+ if (( nval = zend_hash_next_index_insert (Z_ARRVAL_P (container_val ), val ) ) == NULL ) {
633650 zval_ptr_dtor (val );
634651 }
635652 } else {
636653 zend_string * skey = zval_get_string (key );
637- if ((zend_symtable_update (Z_ARRVAL_P (container_val ), skey , val )) == NULL ) {
654+ if ((nval = zend_symtable_update (Z_ARRVAL_P (container_val ), skey , val )) == NULL ) {
638655 zval_ptr_dtor (val );
639656 }
640657 zend_string_release (skey );
@@ -643,7 +660,12 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
643660 }
644661 }
645662
646- msgpack_stack_pop (unpack -> var_hash , key , val );
663+ if (MSGPACK_IS_STACK_VALUE (val )) {
664+ msgpack_stack_pop (unpack -> var_hash , val );
665+ } else {
666+ msgpack_var_replace (val , nval );
667+ }
668+ msgpack_stack_pop (unpack -> var_hash , key );
647669
648670 deps = unpack -> deps - 1 ;
649671 unpack -> stack [deps ]-- ;
0 commit comments