cmark

My personal build of CMark ✏️

Commit
b34af68668c514b73102acc4c32e7bd6ac5a8301
Parent
c737934e286710a2b8094c6255eee98102eed57a
Author
John MacFarlane <jgm@berkeley.edu>
Date

Avoid trying to free string_contents for inlines.

This avoids an unnecessary free(0) -- and perhaps free(???).

However, ltrace reveals that there is still a free(0) happening, with some other source.

Diffstat

1 file changed, 70 insertions, 68 deletions

Status File Name N° Changes Insertions Deletions
Modified src/node.c 138 70 68
diff --git a/src/node.c b/src/node.c
@@ -7,6 +7,73 @@
 static void
 S_node_unlink(cmark_node *node);
 
+static inline bool
+S_is_block(cmark_node *node)
+{
+	if (node == NULL) {
+		return false;
+	}
+	return node->type >= CMARK_NODE_FIRST_BLOCK
+	       && node->type <= CMARK_NODE_LAST_BLOCK;
+}
+
+static inline bool
+S_is_inline(cmark_node *node)
+{
+	if (node == NULL) {
+		return false;
+	}
+	return node->type >= CMARK_NODE_FIRST_INLINE
+	       && node->type <= CMARK_NODE_LAST_INLINE;
+}
+
+static bool
+S_can_contain(cmark_node *node, cmark_node *child)
+{
+	cmark_node *cur;
+
+	if (node == NULL || child == NULL) {
+		return false;
+	}
+
+	// Verify that child is not an ancestor of node or equal to node.
+	cur = node;
+	do {
+		if (cur == child) {
+			return false;
+		}
+		cur = cur->parent;
+	} while (cur != NULL);
+
+	if (child->type == CMARK_NODE_DOCUMENT) {
+		return false;
+	}
+
+	switch (node->type) {
+	case CMARK_NODE_DOCUMENT:
+	case CMARK_NODE_BLOCK_QUOTE:
+	case CMARK_NODE_ITEM:
+		return S_is_block(child)
+		       && child->type != CMARK_NODE_ITEM;
+
+	case CMARK_NODE_LIST:
+		return child->type == CMARK_NODE_ITEM;
+
+	case CMARK_NODE_PARAGRAPH:
+	case CMARK_NODE_HEADER:
+	case CMARK_NODE_EMPH:
+	case CMARK_NODE_STRONG:
+	case CMARK_NODE_LINK:
+	case CMARK_NODE_IMAGE:
+		return S_is_inline(child);
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
 cmark_node*
 cmark_node_new(cmark_node_type type)
 {
@@ -39,7 +106,9 @@ void S_free_nodes(cmark_node *e)
 {
 	cmark_node *next;
 	while (e != NULL) {
-		cmark_strbuf_free(&e->string_content);
+		if (S_is_block(e)) {
+			cmark_strbuf_free(&e->string_content);
+		}
 		switch (e->type) {
 		case NODE_CODE_BLOCK:
 			cmark_chunk_free(&e->as.code.info);
@@ -568,73 +637,6 @@ cmark_node_get_end_column(cmark_node *node)
 	return node->end_column;
 }
 
-static inline bool
-S_is_block(cmark_node *node)
-{
-	if (node == NULL) {
-		return false;
-	}
-	return node->type >= CMARK_NODE_FIRST_BLOCK
-	       && node->type <= CMARK_NODE_LAST_BLOCK;
-}
-
-static inline bool
-S_is_inline(cmark_node *node)
-{
-	if (node == NULL) {
-		return false;
-	}
-	return node->type >= CMARK_NODE_FIRST_INLINE
-	       && node->type <= CMARK_NODE_LAST_INLINE;
-}
-
-static bool
-S_can_contain(cmark_node *node, cmark_node *child)
-{
-	cmark_node *cur;
-
-	if (node == NULL || child == NULL) {
-		return false;
-	}
-
-	// Verify that child is not an ancestor of node or equal to node.
-	cur = node;
-	do {
-		if (cur == child) {
-			return false;
-		}
-		cur = cur->parent;
-	} while (cur != NULL);
-
-	if (child->type == CMARK_NODE_DOCUMENT) {
-		return false;
-	}
-
-	switch (node->type) {
-	case CMARK_NODE_DOCUMENT:
-	case CMARK_NODE_BLOCK_QUOTE:
-	case CMARK_NODE_ITEM:
-		return S_is_block(child)
-		       && child->type != CMARK_NODE_ITEM;
-
-	case CMARK_NODE_LIST:
-		return child->type == CMARK_NODE_ITEM;
-
-	case CMARK_NODE_PARAGRAPH:
-	case CMARK_NODE_HEADER:
-	case CMARK_NODE_EMPH:
-	case CMARK_NODE_STRONG:
-	case CMARK_NODE_LINK:
-	case CMARK_NODE_IMAGE:
-		return S_is_inline(child);
-
-	default:
-		break;
-	}
-
-	return false;
-}
-
 // Unlink a node without adjusting its next, prev, and parent pointers.
 static void
 S_node_unlink(cmark_node *node)