From 3239bb66b9c06c550186addd7c452850aa224ded Mon Sep 17 00:00:00 2001 From: Aaron Son Date: Thu, 27 Feb 2025 16:18:42 -0800 Subject: [PATCH 1/2] go/mysql: conn.go: Fix read-after-recycle bug of the packet byte buffer in COM_STMT_SEND_LONG_DATA. Back ports https://github.com/vitessio/vitess/commit/24820d8101688019d4c83b64d911778450255687 --- go/mysql/conn.go | 5 +---- go/mysql/query.go | 6 +++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go/mysql/conn.go b/go/mysql/conn.go index 34b219e7824..dfb4dde2eec 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -1236,7 +1236,7 @@ func (c *Conn) handleNextCommand(ctx context.Context, handler Handler) error { return err } case ComStmtSendLongData: - stmtID, paramID, chunkData, ok := c.parseComStmtSendLongData(data) + stmtID, paramID, chunk, ok := c.parseComStmtSendLongData(data) c.recycleReadPacket() if !ok { err := fmt.Errorf("error parsing statement send long data from client %v, returning error: %v", c.ConnectionID, data) @@ -1259,9 +1259,6 @@ func (c *Conn) handleNextCommand(ctx context.Context, handler Handler) error { return err } - chunk := make([]byte, len(chunkData)) - copy(chunk, chunkData) - key := fmt.Sprintf("v%d", paramID+1) if val, ok := prepare.BindVars[key]; ok { val.Value = append(val.Value, chunk...) diff --git a/go/mysql/query.go b/go/mysql/query.go index ef9c81a1ac2..b1c59303ceb 100644 --- a/go/mysql/query.go +++ b/go/mysql/query.go @@ -933,7 +933,11 @@ func (c *Conn) parseComStmtSendLongData(data []byte) (uint32, uint16, []byte, bo return 0, 0, nil, false } - return statementID, paramID, data[pos:], true + chunkData := data[pos:] + chunk := make([]byte, len(chunkData)) + copy(chunk, chunkData) + + return statementID, paramID, chunk, true } func (c *Conn) parseComStmtClose(data []byte) (uint32, bool) { From 7a5da6e29232d0ab8d886ddfc42d2b267aa237db Mon Sep 17 00:00:00 2001 From: Aaron Son Date: Thu, 27 Feb 2025 16:29:26 -0800 Subject: [PATCH 2/2] go/mysql: conn.go: Fix read-after-recycle bug in COM_REGISTER_REPLICA and COM_BINLOG_DUMP_GTID. --- go/mysql/conn.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/go/mysql/conn.go b/go/mysql/conn.go index dfb4dde2eec..093b474fb2b 100644 --- a/go/mysql/conn.go +++ b/go/mysql/conn.go @@ -1424,13 +1424,14 @@ func (c *Conn) handleComRegisterReplica(handler Handler, data []byte) (kontinue return true } - c.recycleReadPacket() - replicaHost, replicaPort, replicaUser, replicaPassword, err := c.parseComRegisterReplica(data) if err != nil { log.Errorf("conn %v: parseComRegisterReplica failed: %v", c.ID(), err) return false } + + c.recycleReadPacket() + if err := binlogReplicaHandler.ComRegisterReplica(c, replicaHost, replicaPort, replicaUser, replicaPassword); err != nil { c.writeErrorPacketFromError(err) return false @@ -1449,7 +1450,6 @@ func (c *Conn) handleComBinlogDumpGTID(handler Handler, data []byte) (kontinue b return true } - c.recycleReadPacket() kontinue = true c.startWriterBuffering() @@ -1465,6 +1465,7 @@ func (c *Conn) handleComBinlogDumpGTID(handler Handler, data []byte) (kontinue b log.Errorf("conn %v: parseComBinlogDumpGTID failed: %v", c.ID(), err) return false } + c.recycleReadPacket() if err := binlogReplicaHandler.ComBinlogDumpGTID(c, logFile, logPos, position.GTIDSet); err != nil { log.Error(err.Error()) c.writeErrorPacketFromError(err)