This is an automated email from the ASF dual-hosted git repository.
wasphin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push:
new 5934fc0e Reject empty MySQL response packets (#3536)
5934fc0e is described below
commit 5934fc0e8ce4d7e0b552e4671e7d32c1a11a0813
Author: Xiaofeng Wang <[email protected]>
AuthorDate: Sat Sep 12 16:20:33 2026 +0800
Reject empty MySQL response packets (#3536)
Validate packet payload lengths before reading the response type byte.
This prevents an empty packet from borrowing the first byte of a
following packet during response parsing.
---
src/brpc/policy/mysql/mysql_reply.cpp | 10 ++++++++
test/brpc_mysql_reply_parse_unittest.cpp | 41 ++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/src/brpc/policy/mysql/mysql_reply.cpp
b/src/brpc/policy/mysql/mysql_reply.cpp
index 2f3a9707..1a277339 100644
--- a/src/brpc/policy/mysql/mysql_reply.cpp
+++ b/src/brpc/policy/mysql/mysql_reply.cpp
@@ -200,6 +200,11 @@ ParseError MysqlReply::ConsumePartialIOBuf(butil::IOBuf&
buf,
}
uint8_t header[4 + 1]; // use the extra byte to judge message type
const uint8_t* p = (const uint8_t*)buf.fetch(header, sizeof(header));
+ if (_type == MYSQL_RSP_UNKNOWN &&
+ (p == nullptr || mysql_uint3korr(p) == 0)) {
+ LOG(ERROR) << "Invalid mysql packet with empty payload";
+ return PARSE_ERROR_ABSOLUTELY_WRONG;
+ }
uint8_t type = (_type == MYSQL_RSP_UNKNOWN) ? p[4] : (uint8_t)_type;
// During the connection (auth) phase the server may send an AuthMoreData
// packet (first byte 0x01) as part of the caching_sha2_password exchange
@@ -243,6 +248,11 @@ ParseError MysqlReply::ConsumePartialIOBuf(butil::IOBuf&
buf,
butil::IOBuf discard;
buf.cutn(&discard, amd_total);
const uint8_t* p2 = (const uint8_t*)buf.fetch(header,
sizeof(header));
+ if (p2 == nullptr || mysql_uint3korr(p2) == 0) {
+ LOG(ERROR) << "Invalid mysql packet with empty payload after "
+ "fast-auth marker";
+ return PARSE_ERROR_ABSOLUTELY_WRONG;
+ }
type = p2[4];
} else {
_type = MYSQL_RSP_AUTH_MORE_DATA;
diff --git a/test/brpc_mysql_reply_parse_unittest.cpp
b/test/brpc_mysql_reply_parse_unittest.cpp
index 33ab95a5..f10773db 100644
--- a/test/brpc_mysql_reply_parse_unittest.cpp
+++ b/test/brpc_mysql_reply_parse_unittest.cpp
@@ -101,6 +101,47 @@ TEST(MysqlReplyParseTest, RejectOversizedTextFieldLength) {
ASSERT_EQ(brpc::PARSE_ERROR_ABSOLUTELY_WRONG, rc);
}
+TEST(MysqlReplyParseTest, RejectZeroPayloadPacket) {
+ butil::IOBuf buf;
+ buf.append(std::string("\x00\x00\x00\x01", 4));
+
+ brpc::MysqlReply reply;
+ butil::Arena arena;
+ bool more_results = false;
+ brpc::ParseError rc = reply.ConsumePartialIOBuf(
+ buf, &arena, false, brpc::MYSQL_NORMAL_STATEMENT, &more_results);
+ ASSERT_EQ(brpc::PARSE_ERROR_ABSOLUTELY_WRONG, rc);
+}
+
+TEST(MysqlReplyParseTest, RejectZeroPayloadPacketWithTrailingBytes) {
+ std::string wire("\x00\x00\x00\x01", 4);
+ AppendPacket(&wire, 2, std::string("\x00\x00\x00\x00\x00\x00\x00", 7));
+ butil::IOBuf buf;
+ buf.append(wire);
+
+ brpc::MysqlReply reply;
+ butil::Arena arena;
+ bool more_results = false;
+ brpc::ParseError rc = reply.ConsumePartialIOBuf(
+ buf, &arena, false, brpc::MYSQL_NORMAL_STATEMENT, &more_results);
+ ASSERT_EQ(brpc::PARSE_ERROR_ABSOLUTELY_WRONG, rc);
+}
+
+TEST(MysqlReplyParseTest, RejectZeroPayloadPacketAfterFastAuthMarker) {
+ std::string wire;
+ AppendPacket(&wire, 2, std::string("\x01\x03", 2));
+ wire.append(std::string("\x00\x00\x00\x03", 4));
+ butil::IOBuf buf;
+ buf.append(wire);
+
+ brpc::MysqlReply reply;
+ butil::Arena arena;
+ bool more_results = false;
+ brpc::ParseError rc = reply.ConsumePartialIOBuf(
+ buf, &arena, true, brpc::MYSQL_NORMAL_STATEMENT, &more_results);
+ ASSERT_EQ(brpc::PARSE_ERROR_ABSOLUTELY_WRONG, rc);
+}
+
// A well-formed field whose length matches the bytes present still parses, so
// the guard does not reject legitimate result sets.
TEST(MysqlReplyParseTest, AcceptWellFormedTextField) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]