Issue Description
When a prepared statement is issued with a high enough number of parameters an invalid resulset (no resulset) is received from server side. Both client libraries `libmysqlclient` and `libmariadbclient` has been tested against a MariaDB backend, leading to the same result. A minimal test case that can be compiled against both of these libraries, together with traffic captures is provided for reproducing the issue.
Errors reported by client libraries
libmysqlclient:
error: 'Attempt to read a row while there is no result set associated with the statement'
|
libmariadbclient:
error: 'Commands out of sync; you can't run this command now'
|
Error reported in MariaDB error log
2022-03-11 12:27:00 1708 [Warning] Aborted connection 1708 to db: 'unconnected' user: 'root' host: '127.0.0.1' (Got an error reading communication packets)
|
2022-03-11 12:27:03 1709 [Warning] Aborted connection 1709 to db: 'unconnected' user: 'root' host: '127.0.0.1' (Got an error reading communication packets)
|
Traffic captures showing the issue:
In the following traffic captures it can be seen valid requests (COM_STMT_EXECUTE) and the responses from MariaDB.
Valid request - COM_STMT_EXECUTE - libmariadb_valid_stmt_response.pcapng:
Frame 16: 2006 bytes on wire (16048 bits), 2006 bytes captured (16048 bits) on interface any, id 0
|
Linux cooked capture v1
|
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
|
Transmission Control Protocol, Src Port: 49516, Dst Port: 3306, Seq: 10703, Ack: 28346, Len: 1938
|
[2 Reassembled TCP Segments (10130 bytes): #15(8192), #16(1938)]
|
MySQL Protocol
|
Packet Length: 10126
|
Packet Number: 0
|
Request Command Execute Statement
|
Valid response - BinaryProtocolResulset - libmariadb_valid_stmt_response.pcapng:
Frame 17: 286 bytes on wire (2288 bits), 286 bytes captured (2288 bits) on interface any, id 0
|
Linux cooked capture v1
|
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
|
Transmission Control Protocol, Src Port: 3306, Dst Port: 49516, Seq: 28346, Ack: 12641, Len: 218
|
MySQL Protocol
|
... { More packets } ...
|
MySQL Protocol
|
Packet Length: 5
|
Packet Number: 7
|
Response Code: EOF Packet (0xfe)
|
EOF marker: 254
|
Warnings: 0
|
Server Status: 0x0000
|
Payload: 2200
|
Offending request - COM_STMT_EXECUTE - libmariadb_invalid_stmt_response.pcapng:
Frame 16: 2016 bytes on wire (16128 bits), 2016 bytes captured (16128 bits) on interface any, id 0
|
Linux cooked capture v1
|
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
|
Transmission Control Protocol, Src Port: 49514, Dst Port: 3306, Seq: 10705, Ack: 28374, Len: 1948
|
[2 Reassembled TCP Segments (10140 bytes): #15(8192), #16(1948)]
|
MySQL Protocol
|
Packet Length: 10136
|
Packet Number: 0
|
Request Command Execute Statement
|
Invalid Response - libmariadb_invalid_stmt_response.pcapng:
Expected BinaryProtocolResulset, received just OK packet:
Frame 17: 79 bytes on wire (632 bits), 79 bytes captured (632 bits) on interface any, id 0
|
Linux cooked capture v1
|
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
|
Transmission Control Protocol, Src Port: 3306, Dst Port: 49514, Seq: 28374, Ack: 12653, Len: 11
|
MySQL Protocol
|
Packet Length: 7
|
Packet Number: 1
|
Response Code: OK Packet (0x00)
|
Prefix: 0
|
Length: 0
|
Prefix: 0
|
Length: 0
|
Affected Rows: 0
|
Prefix: 0
|
Length: 0
|
Server Status: 0x0002
|
Warnings: 0
|
Issue Reproduction
Script compilation
Against `libmysqlclient`:
g++ -DLIBMYSQLCLIENT test_stmt_large_param_num.cpp -I/usr/include/mysql -ldl -std=c++11 -lmysqlclient -o libmysql_test_stmt_large_param_num
|
Against `libmariadbclient`:
g++ test_stmt_large_param_num.cpp -I/usr/include/mysql -ldl -std=c++11 -lmariadbclient -o libmariadb_test_stmt_large_param_num
|
Script usage
Using the provided test script it's just enough to use it against a MariaDB, and the issue will be reproduce, script usage is the following:
test_stmt_large_param_num -h <mysql host> -u <mysql user> -p <mysql password> -P <mysql port> -N <stmt_param_num>
|
Where '-N' specifies the number of parameters to be created for the stmt to be issued. Simple testing using the script via:
for i in {500..2000}; do ./libmariadb_test_stmt_large_param_num -h '127.0.0.1' -u root -p root -P 3306 -N $i; if [ $? -ne 0 ]; then echo ArgNum: $i - $(date); break; fi; done
|
Revealed that `1000` appears to be the offending number of parameters that triggers the issue, at least in the used testing environment.
|