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 <noreply@anthropic.com>
This commit is contained in:
Jonathan BennettandClaude authored and GitHub committed 2026-08-13 13:24:00 -04:00
1 parent 30e6e0ec8c
commit faa2c8fc52
1 file changed
+7 -2
+7 -2
View File
@@ -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;