memleak: make notleak() work even before memleak is initalized.
What changed, and why it matters
This is a small internal cleanup in Core Lightning's memory-tracking helpers. It makes the 'notleak' marker safe to use earlier during program startup, before the full memory-leak detection system is ready. There is no direct security vulnerability being fixed; it is a robustness improvement that prevents potential false-positive leak reports or minor memory accounting issues during initialization.
No immediate security action required. Treat as normal code-quality/maintenance patch. Reviewers may want to confirm that tal_free(name) correctly releases the temporary name string without affecting the marked allocation.
Security signals we found
Refactor of memory-leak tracking helper
Removal of early-return based on memleak_track global
Elimination of tmpctx use in notleak_() to avoid uninitialized-context use
No bounds, input, or cryptographic changes
Evidence from the diff
The commit refactors notleak_() in common/memleak.c so it no longer depends on the global memleak_track flag or the tmpctx temporary context. Instead it always renames the tal allocation by appending ‘NOTLEAK’ or ‘NOTLEAK_IGNORE_CHILDREN’. Callers in common/configdir.c and common/trace.c are updated to use the public notleak() helper rather than hand-rolling tal labels. The change removes a special-case ‘_notleak’ suffix check in call_memleak_helpers(). The primary effect is that allocations can be marked non-leaking before memleak tracking is initialized.
Changed components
common/memleak.ccommon/configdir.ccommon/trace.cInspect captured patch +9 / −14
diff --git a/common/configdir.c b/common/configdir.c
index b4e401a1..8bbf29b4 100644
--- a/common/configdir.c
+++ b/common/configdir.c
@@ -9,6 +9,7 @@
#include <ccan/tal/str/str.h>
#include <common/configdir.h>
#include <common/configvar.h>
+#include <common/memleak.h>
#include <common/utils.h>
#include <common/version.h>
@@ -35,8 +36,7 @@ static char *opt_set_abspath(const char *arg, char **p)
/* Tal wrappers for opt. */
static void *opt_allocfn(size_t size)
{
- return tal_arr_label(NULL, char, size,
- TAL_LABEL(opt_allocfn_notleak, ""));
+ return notleak(tal_arr(NULL, char, size));
}
static void *tal_reallocfn(void *ptr, size_t size)
diff --git a/common/memleak.c b/common/memleak.c
index 7ac0da7c..de321a9a 100644
--- a/common/memleak.c
+++ b/common/memleak.c
@@ -58,9 +58,6 @@ struct tal_backtrace {
void *notleak_(void *ptr, bool plus_children)
{
const char *name;
- /* If we're not tracking, don't do anything. */
- if (!memleak_track)
- return cast_const(void *, ptr);
/* We use special tal names to mark notleak */
name = tal_name(ptr);
@@ -69,12 +66,14 @@ void *notleak_(void *ptr, bool plus_children)
/* Don't mark more than once! */
if (!strstr(name, "**NOTLEAK")) {
+ /* Don't use tmpctx: it might not be set up yet! */
if (plus_children)
- name = tal_fmt(tmpctx, "%s **NOTLEAK_IGNORE_CHILDREN**",
+ name = tal_fmt(NULL, "%s **NOTLEAK_IGNORE_CHILDREN**",
name);
else
- name = tal_fmt(tmpctx, "%s **NOTLEAK**", name);
+ name = tal_fmt(NULL, "%s **NOTLEAK**", name);
tal_set_name(ptr, name);
+ tal_free(name);
}
return cast_const(void *, ptr);
@@ -331,8 +330,7 @@ static void call_memleak_helpers(struct htable *memtable, const tal_t *p)
if (strends(name, "struct memleak_helper")) {
const struct memleak_helper *mh = i;
mh->cb(memtable, p);
- } else if (strends(name, " **NOTLEAK**")
- || strends(name, "_notleak")) {
+ } else if (strends(name, " **NOTLEAK**")) {
memleak_ptr(memtable, i);
memleak_scan_obj(memtable, i);
} else if (strends(name,
diff --git a/common/trace.c b/common/trace.c
index 7ffe7eac..e3018a00 100644
--- a/common/trace.c
+++ b/common/trace.c
@@ -5,6 +5,7 @@
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <common/json_stream.h>
+#include <common/memleak.h>
#include <common/pseudorand.h>
#include <common/trace.h>
#include <inttypes.h>
@@ -181,15 +182,11 @@ static inline void trace_check_tree(void) {}
static void trace_init(void)
{
const char *dev_trace_file;
- const char notleak_name[] = "struct span **NOTLEAK**";
if (active_spans)
return;
- active_spans = tal_arrz(NULL, struct span, 1);
- /* We're usually too early for memleak to be initialized, so mark
- * this notleak manually! */
- tal_set_name(active_spans, notleak_name);
+ active_spans = notleak(tal_arrz(NULL, struct span, 1));
current = NULL;
dev_trace_file = getenv("CLN_DEV_TRACE_FILE");
Why this scored 17/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.