@@ -79,11 +79,29 @@ void msgpack_unpacker_static_destroy(void)
7979
8080#define HEAD_BYTE_REQUIRED 0xc1
8181
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;
8590}
8691
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+
87105void _msgpack_unpacker_init (msgpack_unpacker_t * uk )
88106{
89107 msgpack_buffer_init (UNPACKER_BUFFER_ (uk ));
@@ -92,16 +110,6 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
92110
93111 uk -> last_object = Qnil ;
94112 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 ;
105113}
106114
107115void _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
750758
751759int msgpack_unpacker_read (msgpack_unpacker_t * uk , size_t target_stack_depth )
752760{
761+ STACK_INIT (uk );
762+
753763 while (true) {
754764 int r = read_primitive (uk );
755765 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+ }
756770 return r ;
757771 }
758772 if (r == PRIMITIVE_CONTAINER_START ) {
@@ -761,6 +775,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
761775 /* PRIMITIVE_OBJECT_COMPLETE */
762776
763777 if (msgpack_unpacker_stack_is_empty (uk )) {
778+ STACK_FREE (uk );
764779 return PRIMITIVE_OBJECT_COMPLETE ;
765780 }
766781
@@ -785,13 +800,15 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
785800 top -> type = STACK_TYPE_MAP_KEY ;
786801 break ;
787802 case STACK_TYPE_RECURSIVE :
803+ STACK_FREE (uk );
788804 return PRIMITIVE_OBJECT_COMPLETE ;
789805 }
790806 size_t count = -- top -> count ;
791807
792808 if (count == 0 ) {
793809 object_complete (uk , top -> object );
794810 if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
811+ STACK_FREE (uk );
795812 return PRIMITIVE_OBJECT_COMPLETE ;
796813 }
797814 goto container_completed ;
@@ -802,9 +819,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
802819
803820int msgpack_unpacker_skip (msgpack_unpacker_t * uk , size_t target_stack_depth )
804821{
822+ STACK_INIT (uk );
823+
805824 while (true) {
806825 int r = read_primitive (uk );
807826 if (r < 0 ) {
827+ STACK_FREE (uk );
808828 return r ;
809829 }
810830 if (r == PRIMITIVE_CONTAINER_START ) {
@@ -813,6 +833,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
813833 /* PRIMITIVE_OBJECT_COMPLETE */
814834
815835 if (msgpack_unpacker_stack_is_empty (uk )) {
836+ STACK_FREE (uk );
816837 return PRIMITIVE_OBJECT_COMPLETE ;
817838 }
818839
@@ -828,6 +849,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
828849 if (count == 0 ) {
829850 object_complete (uk , Qnil );
830851 if (msgpack_unpacker_stack_pop (uk ) <= target_stack_depth ) {
852+ STACK_FREE (uk );
831853 return PRIMITIVE_OBJECT_COMPLETE ;
832854 }
833855 goto container_completed ;
0 commit comments