[PATCH 3/3] cli/show: handle NULL returns from mime_node_child

Subject: [PATCH 3/3] cli/show: handle NULL returns from mime_node_child

Date: Mon, 10 Aug 2026 20:32:36 -0300

To: David Bremner, notmuch@notmuchmail.org

Cc:

From: David Bremner


mime_node_child has (potentially) returned NULL since it was
introduced, but apparently this did not happen much in practice, since
nobody mentioned segfaults.  Clean that up so that at least notmuch
show does not segfault with empty message attachments anymore [1].

At least in the test case [2], this seems to produce structured output
(json / sexpr) conforming to devel/schemata, since a multipart/* can
have 0 or more children under the 'content' key.

[1] id:20260623074714Z.449345370-stepnem@smrk.net
[2] id:1782193672-98446-mlmmj-36f22ff2@FreeBSD.org
---
 notmuch-show.c    | 27 ++++++++++++++++++---------
 test/T520-show.sh |  1 -
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/notmuch-show.c b/notmuch-show.c
index 8c23f821..22983101 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -637,9 +637,11 @@ format_part_text (const void *ctx, sprinter_t *sp, mime_node_t *node,
 	}
     }
 
-    for (i = 0; i < node->nchildren; i++)
-	format_part_text (ctx, sp, mime_node_child (node, i), indent, params);
-
+    for (i = 0; i < node->nchildren; i++) {
+	mime_node_t *child = mime_node_child (node, i);
+	if (child != NULL)
+	    format_part_text (ctx, sp, child, indent, params);
+    }
     if (GMIME_IS_MESSAGE (node->part))
 	g_mime_stream_printf (stream, "\fbody}\n");
 
@@ -689,10 +691,13 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
 	sp->integer (sp, duplicate > 0 ? duplicate : 1);
 
 	if (output_body) {
-	    sp->map_key (sp, "body");
-	    sp->begin_list (sp);
-	    format_part_sprinter (ctx, sp, mime_node_child (node, 0), -1, true, include_html);
-	    sp->end (sp);
+	    mime_node_t *child = mime_node_child (node, 0);
+	    if (child) {
+		sp->map_key (sp, "body");
+		sp->begin_list (sp);
+		format_part_sprinter (ctx, sp, child, -1, true, include_html);
+		sp->end (sp);
+	    }
 	}
 
 	msg_crypto = mime_node_get_message_crypto_status (node);
@@ -854,8 +859,12 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
 	nclose = 3;
     }
 
-    for (i = 0; i < node->nchildren; i++)
-	format_part_sprinter (ctx, sp, mime_node_child (node, i), -1, true, include_html);
+    for (i = 0; i < node->nchildren; i++) {
+	mime_node_t *child = mime_node_child (node, i);
+	if (child) {
+	    format_part_sprinter (ctx, sp, child, -1, true, include_html);
+	}
+    }
 
     /* Close content structures */
     for (i = 0; i < nclose; i++)
diff --git a/test/T520-show.sh b/test/T520-show.sh
index 9eb49284..25afded7 100755
--- a/test/T520-show.sh
+++ b/test/T520-show.sh
@@ -109,7 +109,6 @@ done
 add_email_corpus broken
 for format in text json sexp; do
     test_begin_subtest "don't crash on empty part ($format)"
-    test_subtest_known_broken
     test_expect_code 0 "notmuch show --format=$format id:1782193672-98446-mlmmj-36f22ff2@FreeBSD.org"
 done
 
-- 
2.53.0

_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: