wwbmmm commented on code in PR #3575:
URL: https://github.com/apache/brpc/pull/3575#discussion_r4163486347


##########
src/brpc/policy/mysql/mysql_reply.cpp:
##########
@@ -745,34 +791,43 @@ ParseError MysqlReply::Error::Parse(butil::IOBuf& buf, 
butil::Arena* arena) {
         return PARSE_OK;
     }
     MysqlHeader header;
-    if (!parse_header(buf, &header)) {
+    butil::IOBuf payload;
+    if (!parse_header(buf, &header, &payload)) {
         return PARSE_ERROR_NOT_ENOUGH_DATA;
     }
-    buf.pop_front(1);  // 0xFF
+    // error message, Null-Terminated string.
+    // payload layout: 0xFF(1) + errcode(2) + '#'(1) + sql_state(5) = 9 bytes;
+    // guard against a malformed short packet to avoid reading past the
+    // packet boundary.
+    if (header.payload_size < 9) {
+        LOG(WARNING) << "MysqlReply::Error::Parse: truncated ERR packet, 
payload_size "
+                   << header.payload_size << " < 9 
(0xFF+errcode+'#'+sql_state)";
+        return PARSE_ERROR_ABSOLUTELY_WRONG;
+    }
+    payload.pop_front(1);  // 0xFF
     {
         uint8_t tmp[2];
-        buf.cutn(tmp, sizeof(tmp));
+        MY_PARSE_CHECK(parse_fixed(payload, tmp, sizeof(tmp)));
         _errcode = mysql_uint2korr(tmp);
     }
-    buf.pop_front(1);  // '#'
+    {
+        uint8_t sharp = 0;
+        MY_PARSE_CHECK(parse_fixed(payload, &sharp, 1));  // '#'
+        if (sharp != '#') {
+            LOG(WARNING) << "MysqlReply::Error::Parse: expected '#' before 
sql_state, got "
+                       << sharp;
+            return PARSE_ERROR_ABSOLUTELY_WRONG;

Review Comment:
   [replied by brpc-oncall robot] Valid compatibility concern, fixed in 
38b3d1e8. `Error::Parse` no longer requires the `#` marker unconditionally. 
After the error code it peeks the next byte: when it is `'#'` the protocol-4.1 
layout is parsed (`#` + 5-byte sql_state + message, and a truncated sql_state 
is still rejected via `parse_fixed`); otherwise the packet is treated as a 
pre-4.1 / initial-handshake error and the whole tail becomes the message with 
an empty sql_state — the same disambiguation MySQL's own clients use, so `FF 10 
04 "Too many connections"` now parses into a proper error reply (code 1040, 
full message). This also removes the pre-existing `payload_size >= 9` guard, 
which rejected any short pre-4.1 error packet regardless of the `#` check, and 
skips the message allocation for an empty tail. The initial-handshake 
regression test you asked for is `AcceptInitialHandshakeErr` (with 
`is_auth=true`), alongside `AcceptProtocol41Err` (4.1 layout keeps its `42000` 
sql_state)
  and `RejectTruncatedSqlState` (`#` present but only 2 of 5 state bytes still 
rejected). All 27 cases in `brpc_mysql_reply_parse_unittest` plus the auth 
packet/handshake/scramble suites pass.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to