@@ -66,19 +66,15 @@ static void rxml_free_node(struct rxml_node *node)
6666
6767 for (attrib_node_head = node -> attrib ; attrib_node_head ; )
6868 {
69- struct rxml_attrib_node * next_attrib = NULL ;
70-
71- next_attrib = (struct rxml_attrib_node * )attrib_node_head -> next ;
72-
73- if (next_attrib )
74- {
75- if (attrib_node_head -> attrib )
76- free (attrib_node_head -> attrib );
77- if (attrib_node_head -> value )
78- free (attrib_node_head -> value );
79- if (attrib_node_head )
80- free (attrib_node_head );
81- }
69+ struct rxml_attrib_node * next_attrib =
70+ (struct rxml_attrib_node * )attrib_node_head -> next ;
71+
72+ if (attrib_node_head -> attrib )
73+ free (attrib_node_head -> attrib );
74+ if (attrib_node_head -> value )
75+ free (attrib_node_head -> value );
76+ if (attrib_node_head )
77+ free (attrib_node_head );
8278
8379 attrib_node_head = next_attrib ;
8480 }
@@ -161,6 +157,7 @@ rxml_document_t *rxml_load_document_string(const char *str)
161157
162158 case YXML_ELEMSTART :
163159 if (node ) {
160+
164161 if (level > stack_i ) {
165162 buf -> stack [stack_i ] = node ;
166163 ++ stack_i ;
@@ -177,7 +174,10 @@ rxml_document_t *rxml_load_document_string(const char *str)
177174 node = doc -> root_node = (rxml_node_t * )calloc (1 , sizeof (* node ));
178175 }
179176
177+ if (node -> name )
178+ free (node -> name );
180179 node -> name = strdup (x .elem );
180+
181181 attr = NULL ;
182182
183183 ++ level ;
@@ -188,7 +188,25 @@ rxml_document_t *rxml_load_document_string(const char *str)
188188
189189 if (valptr > buf -> val ) {
190190 * valptr = '\0' ;
191- node -> data = strdup (buf -> val );
191+
192+ /* Original code was broken here:
193+ * > If an element ended on two successive
194+ * iterations, on the second iteration
195+ * the 'data' for the *previous* node would
196+ * get overwritten
197+ * > This effectively erased the data for the
198+ * previous node, *and* caused a memory leak
199+ * (due to the double strdup())
200+ * It seems the correct thing to do here is
201+ * only copy the data if the current 'level'
202+ * and 'stack index' are the same... */
203+ if (level == stack_i )
204+ {
205+ if (node -> data )
206+ free (node -> data );
207+ node -> data = strdup (buf -> val );
208+ }
209+
192210 valptr = buf -> val ;
193211 }
194212
@@ -211,7 +229,10 @@ rxml_document_t *rxml_load_document_string(const char *str)
211229 else
212230 attr = node -> attrib = (struct rxml_attrib_node * )calloc (1 , sizeof (* attr ));
213231
232+ if (attr -> attrib )
233+ free (attr -> attrib );
214234 attr -> attrib = strdup (x .attr );
235+
215236 valptr = buf -> val ;
216237 break ;
217238
@@ -225,7 +246,11 @@ rxml_document_t *rxml_load_document_string(const char *str)
225246 case YXML_ATTREND :
226247 if (valptr > buf -> val ) {
227248 * valptr = '\0' ;
249+
250+ if (attr -> value )
251+ free (attr -> value );
228252 attr -> value = strdup (buf -> val );
253+
229254 valptr = buf -> val ;
230255 }
231256 break ;
0 commit comments