From 2b9ea1030a98c8722ce2a2db8cbdd26a128295ed Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Thu, 15 Jan 2026 12:28:10 +0100 Subject: [PATCH] Guard error log underflow in parser --- src/RequestParser.cpp | 6 ++++-- test/request_parser_error_log.py | 32 ++++++++++++++++++++++++++++++++ test/run.sh | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 test/request_parser_error_log.py diff --git a/src/RequestParser.cpp b/src/RequestParser.cpp index 215f1a2..46a3da5 100644 --- a/src/RequestParser.cpp +++ b/src/RequestParser.cpp @@ -444,10 +444,12 @@ RequestParser::Status RequestParser::parse(Buffer* buf, int& pos, bool split) SString<64> bufHex; bufHex.printHex(buf->data() + start, buf->length() - start); SString<16> errHex; - errHex.printHex(cursor - 1, end - cursor + 1); + // Clamp errStart to the buffer head to avoid underflow on first-byte errors. + const char* errStart = cursor > buf->data() ? cursor - 1 : cursor; + errHex.printHex(errStart, end - errStart); logDebug("request parse error %d state %d buf:%s errpos %d err:%s", error, mState, bufHex.data(), - pos - 1 - start, errHex.data()); + (errStart - buf->data()) - start, errHex.data()); return ParseError; } return Normal; diff --git a/test/request_parser_error_log.py b/test/request_parser_error_log.py new file mode 100644 index 0000000..735910d --- /dev/null +++ b/test/request_parser_error_log.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# +# Trigger parser errors at the first byte to verify safe error logging. +# + +import socket +from test_util import parse_args, make_client, exit_with_result + + +def run_test(host, port): + try: + sock = socket.create_connection((host, port), timeout=1.0) + sock.sendall(b"!") + sock.close() + except Exception as exc: + print("WARN: invalid byte send failed:", exc) + + try: + c = make_client(host, port) + if c.ping() is not True: + print("FAIL: ping after invalid byte") + return False + except Exception as exc: + print("FAIL: ping after invalid byte:", exc) + return False + return True + + +if __name__ == "__main__": + args = parse_args("Request parser error logging test") + success = run_test(args.host, args.port) + exit_with_result(success, "request parser error logging", "request parser error logging") diff --git a/test/run.sh b/test/run.sh index 2965a34..9336250 100755 --- a/test/run.sh +++ b/test/run.sh @@ -141,6 +141,7 @@ TESTS=( "test/pubsub_parser_reset.py" "test/null_response_handling.py" "test/request_parser_boundary.py" + "test/request_parser_error_log.py" "test/pubsub_long_name.py" "test/pubsub_large_message.py" "test/transaction_forbid.py"