From a7923523878b3bab10a0c0ea028cd618861c8128 Mon Sep 17 00:00:00 2001 From: Weaselbot Date: Mon, 26 Oct 2026 19:19:43 -0400 Subject: [PATCH] Skip DEBUG_VERBOSE end print for point writes Point writes are recorded with the 2-argument interleaved_insert::Result constructor, which leaves endRemaining indeterminate, so the Phase 2 debug print in interleavedWrites read an indeterminate span and, with stack garbage left over from an earlier call, dereferenced a freed pointer. Confirmed with valgrind on a point write following a range write: "Conditional jump or move depends on uninitialised value(s)" and "Invalid read of size 1" at ConflictSet.cpp:4984, and ASan heap-use-after-free in the same place. Only print the end search path and spans for range writes, mirroring the `if (e != nullptr)` check that already guards the endInsertionPoint forwarding-chain fixup a few lines above. Production code already treats endRemaining as range-write only, so nothing else changes. --- ConflictSet.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 553fb11..2c5f795 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -4979,9 +4979,11 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { fprintf(stderr, "search path: %s, begin: %s\n", getSearchPathPrintable(b).c_str(), printable(context.results[i].remaining).c_str()); - fprintf(stderr, "search path: %s, end: %s\n", - getSearchPathPrintable(e).c_str(), - printable(context.results[i].endRemaining).c_str()); + if (e != nullptr) { + fprintf(stderr, "search path: %s, end: %s\n", + getSearchPathPrintable(e).c_str(), + printable(context.results[i].endRemaining).c_str()); + } } #endif -- 2.43.0