From 19a847d40c03213fd05693b1b43d974ce0bfe6bf Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 5 Nov 2020 17:37:55 +0100 Subject: [PATCH] MDEV-19838: followup to make happy following protocol implementations: - mysqlnd from PHP < 7.3 - mysql-connector-python any version - mysql-connector-java any version Relaxed check about garbage at the end of the packet in case of no parameters. Added check for array binding. Fixed test according to the new paradigm (allow junk at the end of the packet) --- sql/sql_prepare.cc | 21 +++++++++++++++++---- tests/mysql_client_test.c | 7 +++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 11edd577309aa..4bf8142959d24 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3271,10 +3271,19 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length) void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length) { uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround + DBUG_ENTER("mysqld_stmt_execute_bulk"); + + const uint packet_header_lenght= 4 + 2; //ID & 2 bytes of flags + + if (packet_length < packet_header_lenght) + { + my_error(ER_MALFORMED_PACKET, MYF(0)); + DBUG_VOID_RETURN; + } + ulong stmt_id= uint4korr(packet); uint flags= (uint) uint2korr(packet + 4); uchar *packet_end= packet + packet_length; - DBUG_ENTER("mysqld_stmt_execute_bulk"); if (!(thd->client_capabilities & MARIADB_CLIENT_STMT_BULK_OPERATIONS)) @@ -3282,16 +3291,18 @@ void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length) DBUG_PRINT("error", ("An attempt to execute bulk operation without support")); my_error(ER_UNSUPPORTED_PS, MYF(0)); + DBUG_VOID_RETURN; } /* Check for implemented parameters */ if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES)) { DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags)); my_error(ER_UNSUPPORTED_PS, MYF(0)); + DBUG_VOID_RETURN; } /* stmt id and two bytes of flags */ - packet+= 4 + 2; + packet+= packet_header_lenght; mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE, (flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES)); DBUG_VOID_RETURN; @@ -3368,9 +3379,11 @@ stmt_execute_packet_sanity_check(Prepared_statement *stmt, { /* If there is no parameters, this should be normally already end - of the packet. If it's not - then error + of the packet, but it is not a problem if something left (popular + mistake in protocol implementation) because we will not read anymore + from the buffer. */ - return (packet_end > packet); + return false; } return false; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 058168eedd54b..93f23236dbc9c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20032,8 +20032,11 @@ static void test_mdev19838() " VALUES " "(0x1111111111111111)", -1); - /* Expecting an error if parameters are sent */ - DIE_UNLESS(rc != 0 || paramCount == 0); + /* + We allow junk at the end of the packet in case of + no parameters. So it will succeed. + */ + DIE_UNLESS(rc == 0); } mysql_stmt_close(stmt);