From faa2c8fc524ad3c46018e6d596409eb43aa3d02f Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Thu, 13 Aug 2026 12:24:00 -0500 Subject: [PATCH] fix(portduino): don't segfault writing the trace file (#11493) The TraceFile path took the first variadic argument as a char* and streamed it, which only held while the tree's sole LOG_TRACE sites were LOG_TRACE("%s", json). Trace-level lines without a string argument (e.g. "Filesystem files:" from fsInit) read a garbage pointer and crashed meshtasticd at boot whenever Logging.TraceFile was configured. Format the message instead. The buffer covers the worst-case packet JSON (233-byte payload escaped 6x plus metadata, ~1.7 KB); the trace file is written untruncated today, so it must not be sized below that. Fixes #11490 Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 Co-authored-by: Claude --- src/RedirectablePrint.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index f0ebbcc208..66a266d960 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -302,13 +302,18 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...) // level trace is special, two possible ways to handle it. if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) { if (portduino_config.traceFilename != "") { + // Format the message rather than assuming the first vararg is a string: not every + // LOG_TRACE call passes one, and reading a char* that isn't there segfaults. Sized for + // the worst-case packet JSON (233-byte payload escaped 6x, plus metadata ~= 1.7 KB). + char traceBuf[2048]; va_list arg; va_start(arg, format); + vsnprintf(traceBuf, sizeof(traceBuf), format, arg); + va_end(arg); try { - traceFile << va_arg(arg, char *) << std::endl; + traceFile << traceBuf << std::endl; } catch (const std::ios_base::failure &e) { } - va_end(arg); } if (portduino_config.logoutputlevel < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) { return;