Handle vsnprintf errors in buffer

This commit is contained in:
Julien Letessier 2026-01-15 12:57:36 +01:00
parent 33601ea2f0
commit 2a431ccee6
4 changed files with 79 additions and 0 deletions

View File

@ -82,6 +82,10 @@ Buffer* Buffer::fappend(const char* fmt, ...)
int len = room();
int n = vsnprintf(dat, len, fmt, ap);
va_end(ap);
if (n < 0) {
// Formatting failed; keep buffer length unchanged.
return nullptr;
}
if (n >= len) {
if (n > MaxBufFmtAppendLen) {
return nullptr;
@ -104,6 +108,11 @@ Buffer* Buffer::vfappend(const char* fmt, va_list ap)
va_list aq;
va_copy(aq, ap);
int n = vsnprintf(dat, len, fmt, ap);
if (n < 0) {
// Formatting failed; keep buffer length unchanged.
va_end(aq);
return nullptr;
}
if (n >= len) {
if (n > MaxBufFmtAppendLen) {
va_end(aq);

20
test/buffer_vsnprintf.cpp Normal file
View File

@ -0,0 +1,20 @@
/*
* Minimal test for Buffer::fappend negative vsnprintf handling.
*/
#include "../src/Buffer.h"
#include "../src/Logger.h"
int main() {
Logger::gInst = nullptr;
Buffer* buf = BufferAlloc::create();
int before = buf->length();
Buffer* ret = buf->fappend("%");
if (ret && ret->length() < before) {
return 1;
}
if (buf->length() < before) {
return 2;
}
return 0;
}

49
test/buffer_vsnprintf.py Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
#
# Build and run the Buffer::fappend 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", "buffer_vsnprintf.cpp")
if not os.path.exists(src):
print("FAIL: buffer_vsnprintf.cpp not found")
return False
with tempfile.TemporaryDirectory() as tmp:
exe = os.path.join(tmp, "buffer_vsnprintf")
cmd = [
"g++",
"-std=c++11",
src,
os.path.join(project_root, "src", "Buffer.cpp"),
os.path.join(project_root, "src", "Alloc.cpp"),
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 buffer_vsnprintf:", exc)
return False
try:
subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as exc:
print("FAIL: buffer_vsnprintf returned", exc.returncode)
return False
return True
if __name__ == "__main__":
_ = parse_args("Buffer vsnprintf test")
root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
success = run_test(root)
exit_with_result(success, "buffer vsnprintf", "buffer vsnprintf")

View File

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