Handle vsnprintf errors in logger

This commit is contained in:
Julien Letessier 2026-01-15 12:59:03 +01:00
parent 2a431ccee6
commit 3146ae0adc
4 changed files with 72 additions and 0 deletions

View File

@ -59,6 +59,16 @@ void LogUnit::vformat(LogLevel::Type level, const char* file, int line, const ch
mLen += n; mLen += n;
len -= n; len -= n;
n = vsnprintf(p, len, fmt, ap); n = vsnprintf(p, len, fmt, ap);
if (n < 0) {
// Formatting failed; keep existing prefix and finish the line.
if (mLen < MaxLogLen - 1) {
mBuf[mLen++] = '\n';
} else {
mBuf[MaxLogLen - 1] = '\n';
mLen = MaxLogLen;
}
return;
}
mLen += n; mLen += n;
if (mLen >= MaxLogLen) { if (mLen >= MaxLogLen) {
mLen = MaxLogLen - 1; mLen = MaxLogLen - 1;

View File

@ -0,0 +1,14 @@
/*
* Minimal test for LogUnit::vformat negative vsnprintf handling.
*/
#include "../src/Logger.h"
int main() {
LogUnit unit;
unit.format(LogLevel::Info, __FILE__, __LINE__, "%");
if (unit.length() < 0) {
return 1;
}
return 0;
}

47
test/logunit_vsnprintf.py Normal file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
#
# Build and run the LogUnit::vformat vsnprintf edge-case test.
#
import os
import subprocess
import tempfile
from test_util import parse_args, exit_with_result
def run_test(project_root):
src = os.path.join(project_root, "test", "logunit_vsnprintf.cpp")
if not os.path.exists(src):
print("FAIL: logunit_vsnprintf.cpp not found")
return False
with tempfile.TemporaryDirectory() as tmp:
exe = os.path.join(tmp, "logunit_vsnprintf")
cmd = [
"g++",
"-std=c++11",
src,
os.path.join(project_root, "src", "Logger.cpp"),
os.path.join(project_root, "src", "LogFileSink.cpp"),
os.path.join(project_root, "src", "Timer.cpp"),
"-o",
exe,
]
try:
subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except Exception as exc:
print("FAIL: compile logunit_vsnprintf:", exc)
return False
try:
subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as exc:
print("FAIL: logunit_vsnprintf returned", exc.returncode)
return False
return True
if __name__ == "__main__":
_ = parse_args("LogUnit vsnprintf test")
root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
success = run_test(root)
exit_with_result(success, "logunit vsnprintf", "logunit vsnprintf")

View File

@ -146,6 +146,7 @@ TESTS=(
"test/request_parser_long_command.py" "test/request_parser_long_command.py"
"test/signal_handling.py" "test/signal_handling.py"
"test/buffer_vsnprintf.py" "test/buffer_vsnprintf.py"
"test/logunit_vsnprintf.py"
"test/pubsub_long_name.py" "test/pubsub_long_name.py"
"test/pubsub_large_message.py" "test/pubsub_large_message.py"
"test/transaction_forbid.py" "test/transaction_forbid.py"