cmark

My personal build of CMark ✏️

Commit
90c48e849440e50b3fef21f0cd6c38b998490073
Parent
9d33831ee4008a795ccec026ce65e424d15f9eaa
Author
John MacFarlane <jgm@berkeley.edu>
Date

free_inlines: use non-recursive algorithm.

This will help avoid stack overflows in deeply nested structures. Partially addresses #187 (still need to do renderers).

Diffstat

1 file changed, 22 insertions, 3 deletions

Status File Name N° Changes Insertions Deletions
Modified src/inlines.c 25 22 3
diff --git a/src/inlines.c b/src/inlines.c
@@ -121,10 +121,29 @@ inline static node_inl* make_simple(int t)
 #define make_emph(contents) make_inlines(INL_EMPH, contents)
 #define make_strong(contents) make_inlines(INL_STRONG, contents)
 
-// Free an inline list.
+// Utility function used by free_inlines
+void splice_into_list(node_inl* e, node_inl* children) {
+	node_inl * tmp;
+	tmp = children;
+	if (!tmp) {
+	    return ;
+	}
+	// Find last child
+	while (tmp->next) {
+	    tmp = tmp->next;
+	}
+	// Splice children into list
+	tmp->next = e->next;
+	e->next = children;
+	return ;
+}
+
+// Free an inline list.  Avoid recursion to prevent stack overflows
+// on deeply nested structures.
 extern void free_inlines(node_inl* e)
 {
 	node_inl * next;
+
 	while (e != NULL) {
 		switch (e->tag){
 		case INL_STRING:
@@ -139,11 +158,11 @@ extern void free_inlines(node_inl* e)
 		case INL_IMAGE:
 			free(e->content.linkable.url);
 			free(e->content.linkable.title);
-			free_inlines(e->content.linkable.label);
+			splice_into_list(e, e->content.linkable.label);
 			break;
 		case INL_EMPH:
 		case INL_STRONG:
-			free_inlines(e->content.inlines);
+		        splice_into_list(e, e->content.inlines);
 			break;
 		default:
 			break;