lightningd: test for very long log entries
What changed, and why it matters
This commit adds a test that reveals Core Lightning can crash when a plugin produces an extremely long log message. The crash happens because the logging code sometimes allocates memory using one method but tries to free it with another, leading to an invalid-pointer error and an abort. The commit only adds the failing test; it does not include the actual fix, so the vulnerability remains unpatched in this commit.
Treat this as a denial-of-service issue: any plugin (including a malicious or compromised plugin) can crash the lightningd daemon by emitting a very long log line. The fix should ensure the logging path consistently uses the correct allocator for the active buffer, or always copies/truncates long lines through a single allocation path. Review commit 4d8f923a9a1468b8987dbb48e8fc988747f8c62f to identify the regression and apply a patch before this test is merged without xfail.
Security signals we found
Heap allocator mismatch (libc free on tal-allocated pointer)
Denial-of-service crash (SIGABRT) from plugin-generated log input
Use of xfail test to document a reproducible crash
Crash path crosses plugin JSON-RPC boundary
Evidence from the diff
The new test test_long_logs creates an inline plugin that emits a 300,000-character log line via plugin.log. The commit message explains that logv in lightningd/log.c uses vasprintf for normal log lines and frees the result with free, but for very long lines it switches to tal_fmt, which returns a tal-allocated pointer. Calling libc free on a tal pointer causes heap corruption (free(): invalid pointer) and SIGABRT. The test is marked xfail(strict=True), meaning it documents the bug and is expected to fail until a fix lands. The stack trace in the commit message confirms the crash path: plugin_read_json -> plugin_notification_handle -> plugin_log_handle -> log_ -> logv -> __GI___libc_free.
Changed components
lightningd/log.clightningd/plugin.cplugin logging interfaceInspect captured patch +17 / −0
diff --git a/tests/test_misc.py b/tests/test_misc.py
index ff30642d..b5f07c67 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -5405,3 +5405,20 @@ def test_tracing_socket(node_factory):
for key in ("id", "name", "timestamp", "duration", "traceId"):
assert key in span, f"Missing key {key} in span {span}"
assert span["localEndpoint"] == {"serviceName": "lightningd"}
+
+
+@pytest.mark.xfail(strict=True)
+def test_long_logs(node_factory):
+ """A plugin that creates a very long log entry. Lightningd should truncate
+ the output and not crash."""
+
+ def setup(plugin):
+ @plugin.method("produce-log")
+ def prod_log(plugin):
+ """Produce a silly and very long log message."""
+ plugin.log("X" * 300000)
+ return {}
+
+ l1 = node_factory.get_node(inline_plugin=setup)
+ l1.rpc.call("produce-log")
+
Why this scored 62/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.