Made additional MySQL fixes.

1) There are a couple more places where the new protocol uses and OK
packet instead of the deprecated EOF.

2) With > 255 results, we could end up in an situation where the uint8
sequence number would wrap, and we'd naively think it'd be a new
handshake.

Now, we track the previous sequence number, and assume overflow if it
was 255 previously and 0 now.

We also reset the previous sequence number to 0 in various packets
that we'd expect at the end of other commands.
This commit is contained in:
Vlad Grigorescu 2020-03-06 22:41:36 -06:00
parent 5a1a9ba98e
commit 6667af85ca

View file

@ -177,9 +177,12 @@ type Header = record {
len : uint32 = to_int()(le_len) + 4; len : uint32 = to_int()(le_len) + 4;
} &length=4; } &length=4;
type Server_Message(seq_id: uint8, pkt_len: uint32) = case seq_id of { type Server_Message(seq_id: uint8, pkt_len: uint32) = case is_initial of {
0 -> initial_handshake: Initial_Handshake_Packet; true -> initial_handshake: Initial_Handshake_Packet;
default -> command_response : Command_Response(pkt_len); false -> command_response : Command_Response(pkt_len);
} &let {
is_initial : bool = (seq_id == 0) && ($context.connection.get_previous_seq_id() != 255);
update_seq_id : bool = $context.connection.set_previous_seq_id(seq_id);
}; };
type Client_Message(state: int) = case state of { type Client_Message(state: int) = case state of {
@ -270,7 +273,7 @@ type Command_Response(pkt_len: uint32) = case $context.connection.get_expectatio
EXPECT_REST_OF_PACKET -> rest : bytestring &restofdata; EXPECT_REST_OF_PACKET -> rest : bytestring &restofdata;
EXPECT_STATUS -> status : Command_Response_Status; EXPECT_STATUS -> status : Command_Response_Status;
EXPECT_AUTH_SWITCH -> auth_switch : AuthSwitchRequest; EXPECT_AUTH_SWITCH -> auth_switch : AuthSwitchRequest;
EXPECT_EOF -> eof : EOF1; EXPECT_EOF -> eof : EOFIfLegacy;
default -> unknown : empty; default -> unknown : empty;
}; };
@ -311,20 +314,25 @@ type ColumnDefinition = record {
update_expectation: bool = $context.connection.set_next_expected($context.connection.get_remaining_cols() > 0 ? EXPECT_COLUMN_DEFINITION : EXPECT_EOF); update_expectation: bool = $context.connection.set_next_expected($context.connection.get_remaining_cols() > 0 ? EXPECT_COLUMN_DEFINITION : EXPECT_EOF);
}; };
type EOFOrOK = case $context.connection.get_deprecate_eof() of {
false -> eof: EOF_Packet;
true -> ok: OK_Packet;
};
type ColumnDefinitionOrEOF(pkt_len: uint32) = record { type ColumnDefinitionOrEOF(pkt_len: uint32) = record {
marker : uint8; marker : uint8;
def_or_eof: case is_eof of { def_or_eof: case is_eof of {
true -> eof: EOF_Packet; true -> eof: EOFOrOK;
false -> def: ColumnDefinition41(marker); false -> def: ColumnDefinition41(marker);
} &requires(is_eof); } &requires(is_eof);
} &let { } &let {
is_eof: bool = (marker == 0xfe && pkt_len <= 13); is_eof: bool = (marker == 0xfe && pkt_len < 13);
}; };
type EOF1 = case $context.connection.get_deprecate_eof() of { type EOFIfLegacy = case $context.connection.get_deprecate_eof() of {
false -> eof: EOF_Packet; false -> eof: EOF_Packet;
true -> ok: OK_Packet; true -> none: empty;
} &let { } &let {
update_result_seen: bool = $context.connection.set_results_seen(0); update_result_seen: bool = $context.connection.set_results_seen(0);
update_expectation: bool = $context.connection.set_next_expected(EXPECT_RESULTSET); update_expectation: bool = $context.connection.set_next_expected(EXPECT_RESULTSET);
@ -333,11 +341,11 @@ type EOF1 = case $context.connection.get_deprecate_eof() of {
type Resultset(pkt_len: uint32) = record { type Resultset(pkt_len: uint32) = record {
marker : uint8; marker : uint8;
row_or_eof: case is_eof of { row_or_eof: case is_eof of {
true -> eof: EOF_Packet; true -> eof: EOFOrOK;
false -> row: ResultsetRow(marker); false -> row: ResultsetRow(marker);
} &requires(is_eof); } &requires(is_eof);
} &let { } &let {
is_eof : bool = (marker == 0xfe && pkt_len <= 13); is_eof : bool = (marker == 0xfe && pkt_len < 13);
update_result_seen: bool = $context.connection.inc_results_seen(); update_result_seen: bool = $context.connection.inc_results_seen();
update_expectation: bool = $context.connection.set_next_expected(is_eof ? NO_EXPECTATION : EXPECT_RESULTSET); update_expectation: bool = $context.connection.set_next_expected(is_eof ? NO_EXPECTATION : EXPECT_RESULTSET);
}; };
@ -406,6 +414,7 @@ type EOF_Packet = record {
refine connection MySQL_Conn += { refine connection MySQL_Conn += {
%member{ %member{
uint8 version_; uint8 version_;
uint8 previous_seq_id_;
int state_; int state_;
Expected expected_; Expected expected_;
uint32 col_count_; uint32 col_count_;
@ -416,6 +425,7 @@ refine connection MySQL_Conn += {
%init{ %init{
version_ = 0; version_ = 0;
previous_seq_id_ = 0;
state_ = CONNECTION_PHASE; state_ = CONNECTION_PHASE;
expected_ = EXPECT_STATUS; expected_ = EXPECT_STATUS;
col_count_ = 0; col_count_ = 0;
@ -435,6 +445,17 @@ refine connection MySQL_Conn += {
return true; return true;
%} %}
function get_previous_seq_id(): uint8
%{
return previous_seq_id_;
%}
function set_previous_seq_id(s: uint8): bool
%{
previous_seq_id_ = s;
return true;
%}
function get_state(): int function get_state(): int
%{ %{
return state_; return state_;