Guard error log underflow in parser

This commit is contained in:
Julien Letessier 2026-01-15 12:28:10 +01:00
parent 7a949b6e7f
commit 2b9ea1030a
3 changed files with 37 additions and 2 deletions

View File

@ -444,10 +444,12 @@ RequestParser::Status RequestParser::parse(Buffer* buf, int& pos, bool split)
SString<64> bufHex; SString<64> bufHex;
bufHex.printHex(buf->data() + start, buf->length() - start); bufHex.printHex(buf->data() + start, buf->length() - start);
SString<16> errHex; 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", logDebug("request parse error %d state %d buf:%s errpos %d err:%s",
error, mState, bufHex.data(), error, mState, bufHex.data(),
pos - 1 - start, errHex.data()); (errStart - buf->data()) - start, errHex.data());
return ParseError; return ParseError;
} }
return Normal; return Normal;

View File

@ -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")

View File

@ -141,6 +141,7 @@ TESTS=(
"test/pubsub_parser_reset.py" "test/pubsub_parser_reset.py"
"test/null_response_handling.py" "test/null_response_handling.py"
"test/request_parser_boundary.py" "test/request_parser_boundary.py"
"test/request_parser_error_log.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"