Skip to content

Commit 4bf929a

Browse files
committed
conn: handle initial error packet correctly
If we haven't completed the hashshake the server will not be aware of our capabilities and so its will packets behave as if we have none. This is necessary to correcly parse an initial error packet which never contains an SQL State field even if the client capabilities will eventually contain CLIENT_PROTOCOL_41. https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase.html Signed-off-by: Petros Angelatos <[email protected]>
1 parent d596978 commit 4bf929a

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/conn/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct ConnInner {
102102
status: StatusFlags,
103103
last_ok_packet: Option<OkPacket<'static>>,
104104
last_err_packet: Option<mysql_common::packets::ServerError<'static>>,
105+
handshake_complete: bool,
105106
pool: Option<Pool>,
106107
pending_result: std::result::Result<Option<PendingResult>, ServerError>,
107108
tx_status: TxStatus,
@@ -147,6 +148,7 @@ impl ConnInner {
147148
status: StatusFlags::empty(),
148149
last_ok_packet: None,
149150
last_err_packet: None,
151+
handshake_complete: false,
150152
stream: None,
151153
is_mariadb: false,
152154
version: (0, 0, 0),
@@ -585,6 +587,7 @@ impl Conn {
585587
handshake_response.serialize(buf.as_mut());
586588

587589
self.write_packet(buf).await?;
590+
self.inner.handshake_complete = true;
588591
Ok(())
589592
}
590593

@@ -789,7 +792,19 @@ impl Conn {
789792
if let Ok(ok_packet) = ok_packet {
790793
self.handle_ok(ok_packet.into_owned());
791794
} else {
792-
let err_packet = ParseBuf(packet).parse::<ErrPacket>(self.capabilities());
795+
// If we haven't completed the handshake the server will not be aware of our
796+
// capabilities and so it will behave as if we have none. In particular, the error
797+
// packet will not contain a SQL State field even if our capabilities do contain the
798+
// `CLIENT_PROTOCOL_41` flag. Therefore it is necessary to parse an incoming packet
799+
// with no capability assumptions if we have not completed the handshake.
800+
//
801+
// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase.html
802+
let capabilities = if self.inner.handshake_complete {
803+
self.capabilities()
804+
} else {
805+
CapabilityFlags::empty()
806+
};
807+
let err_packet = ParseBuf(packet).parse::<ErrPacket>(capabilities);
793808
if let Ok(err_packet) = err_packet {
794809
self.handle_err(err_packet)?;
795810
return Ok(true);

0 commit comments

Comments
 (0)