@@ -79,11 +79,29 @@ void msgpack_unpacker_static_destroy(void)
79
79
80
80
#define HEAD_BYTE_REQUIRED 0xc1
81
81
82
- static inline void _msgpack_unpacker_stack_init (msgpack_unpacker_stack_t * stack ) {
83
- stack -> capacity = MSGPACK_UNPACKER_STACK_CAPACITY ;
84
- stack -> data = msgpack_rmem_alloc (& s_stack_rmem );
82
+ static inline bool _msgpack_unpacker_stack_init (msgpack_unpacker_stack_t * stack ) {
83
+ if (!stack -> data ) {
84
+ stack -> capacity = MSGPACK_UNPACKER_STACK_CAPACITY ;
85
+ stack -> data = msgpack_rmem_alloc (& s_stack_rmem );
86
+ stack -> depth = 0 ;
87
+ return true;
88
+ }
89
+ return false;
85
90
}
86
91
92
+ static inline void _msgpack_unpacker_free_stack (msgpack_unpacker_stack_t * stack ) {
93
+ if (stack -> data ) {
94
+ if (!msgpack_rmem_free (& s_stack_rmem , stack -> data )) {
95
+ rb_bug ("Failed to free an rmem pointer, memory leak?" );
96
+ }
97
+ stack -> data = NULL ;
98
+ stack -> depth = 0 ;
99
+ }
100
+ }
101
+
102
+ #define STACK_INIT (uk ) bool stack_allocated = _msgpack_unpacker_stack_init(&uk->stack);
103
+ #define STACK_FREE (uk ) if (stack_allocated) { _msgpack_unpacker_free_stack(&uk->stack); }
104
+
87
105
void _msgpack_unpacker_init (msgpack_unpacker_t * uk )
88
106
{
89
107
msgpack_buffer_init (UNPACKER_BUFFER_ (uk ));
@@ -92,16 +110,6 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
92
110
93
111
uk -> last_object = Qnil ;
94
112
uk -> reading_raw = Qnil ;
95
-
96
- _msgpack_unpacker_stack_init (& uk -> stack );
97
- }
98
-
99
- static inline void _msgpack_unpacker_free_stack (msgpack_unpacker_stack_t * stack ) {
100
- if (!msgpack_rmem_free (& s_stack_rmem , stack -> data )) {
101
- rb_bug ("Failed to free an rmem pointer, memory leak?" );
102
- }
103
- stack -> data = NULL ;
104
- stack -> depth = 0 ;
105
113
}
106
114
107
115
void _msgpack_unpacker_destroy (msgpack_unpacker_t * uk )
@@ -750,9 +758,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
750
758
751
759
int msgpack_unpacker_read (msgpack_unpacker_t * uk , size_t target_stack_depth )
752
760
{
761
+ STACK_INIT (uk );
762
+
753
763
while (true) {
754
764
int r = read_primitive (uk );
755
765
if (r < 0 ) {
766
+ if (r != PRIMITIVE_EOF ) {
767
+ // We keep the stack on EOF as the parsing may be resumed.
768
+ STACK_FREE (uk );
769
+ }
756
770
return r ;
757
771
}
758
772
if (r == PRIMITIVE_CONTAINER_START ) {
@@ -761,6 +775,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
761
775
/* PRIMITIVE_OBJECT_COMPLETE */
762
776
763
777
if (msgpack_unpacker_stack_is_empty (uk )) {
778
+ STACK_FREE (uk );
764
779
return PRIMITIVE_OBJECT_COMPLETE ;
765
780
}
766
781
@@ -785,13 +800,15 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
785
800
top -> type = STACK_TYPE_MAP_KEY ;
786
801
break ;
787
802
case STACK_TYPE_RECURSIVE :
803
+ STACK_FREE (uk );
788
804
return PRIMITIVE_OBJECT_COMPLETE ;
789
805
}
790
806
size_t count = -- top -> count ;
791
807
792
808
if (count == 0 ) {
793
809
object_complete (uk , top -> object );
794
810
if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
811
+ STACK_FREE (uk );
795
812
return PRIMITIVE_OBJECT_COMPLETE ;
796
813
}
797
814
goto container_completed ;
@@ -802,9 +819,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
802
819
803
820
int msgpack_unpacker_skip (msgpack_unpacker_t * uk , size_t target_stack_depth )
804
821
{
822
+ STACK_INIT (uk );
823
+
805
824
while (true) {
806
825
int r = read_primitive (uk );
807
826
if (r < 0 ) {
827
+ STACK_FREE (uk );
808
828
return r ;
809
829
}
810
830
if (r == PRIMITIVE_CONTAINER_START ) {
@@ -813,6 +833,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
813
833
/* PRIMITIVE_OBJECT_COMPLETE */
814
834
815
835
if (msgpack_unpacker_stack_is_empty (uk )) {
836
+ STACK_FREE (uk );
816
837
return PRIMITIVE_OBJECT_COMPLETE ;
817
838
}
818
839
@@ -828,6 +849,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
828
849
if (count == 0 ) {
829
850
object_complete (uk , Qnil );
830
851
if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
852
+ STACK_FREE (uk );
831
853
return PRIMITIVE_OBJECT_COMPLETE ;
832
854
}
833
855
goto container_completed ;
0 commit comments