Skip to content

Commit 3d70e80

Browse files
author
Arun Kuruvila
committed
Merge branch 'mysql-5.6' into mysql-5.7
2 parents 6b6ea07 + 5eb6d46 commit 3d70e80

File tree

4 files changed

+150
-6
lines changed

4 files changed

+150
-6
lines changed

libmysqld/lib_sql.cc

+94-1
Original file line numberDiff line numberDiff line change
@@ -328,15 +328,26 @@ static my_bool emb_read_query_result(MYSQL *mysql)
328328
return 0;
329329
}
330330

331+
#define HEADER_SIZE 9
331332
static int emb_stmt_execute(MYSQL_STMT *stmt)
332333
{
333334
DBUG_ENTER("emb_stmt_execute");
334-
uchar header[5];
335+
/*
336+
Header size is made similar to non-embedded library.
337+
It should be consistent across embedded and non-embedded
338+
libraries.
339+
*/
340+
uchar header[HEADER_SIZE];
335341
THD *thd;
336342
my_bool res;
337343

338344
int4store(header, stmt->stmt_id);
339345
header[4]= (uchar) stmt->flags;
346+
/*
347+
Dummy value is stored in the last 4 bytes of the header
348+
to make it consistent with non-embedded library.
349+
*/
350+
int4store(header + 5, 1);
340351
thd= (THD*)stmt->mysql->thd;
341352
thd->client_param_count= stmt->param_count;
342353
thd->client_params= stmt->params;
@@ -1270,6 +1281,16 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
12701281
}
12711282

12721283

1284+
void Protocol_binary::start_row()
1285+
{
1286+
MYSQL_DATA *data= m_thd->cur_data;
1287+
next_mysql_field= data->embedded_info->fields_list;
1288+
packet->length(bit_fields + 1);
1289+
memset(const_cast<char*>(packet->ptr()), 0, 1 + bit_fields);
1290+
field_pos= 0;
1291+
}
1292+
1293+
12731294
void Protocol_text::start_row()
12741295
{
12751296
MYSQL_ROWS *cur;
@@ -1310,6 +1331,78 @@ bool Protocol_text::store_null()
13101331
}
13111332

13121333

1334+
bool Protocol_binary::net_store_data(const uchar *from, size_t length)
1335+
{
1336+
if (!m_thd->mysql) // bootstrap file handling
1337+
return 0;
1338+
1339+
size_t packet_length= packet->length();
1340+
/*
1341+
The +9 comes from that strings of length longer than 16M require
1342+
9 bytes to be stored (see net_store_length).
1343+
*/
1344+
if (packet_length + 9 + length > packet->alloced_length() &&
1345+
packet->mem_realloc(packet_length + 9 + length))
1346+
return 1;
1347+
uchar *to= net_store_length((uchar*)packet->ptr() + packet_length, length);
1348+
memcpy(to, from, length);
1349+
packet->length((uint)(to + length - (uchar*)packet->ptr()));
1350+
if (next_mysql_field->max_length < length)
1351+
next_mysql_field->max_length= length;
1352+
++next_mysql_field;
1353+
return 0;
1354+
}
1355+
1356+
bool Protocol_binary::net_store_data(const uchar *from, size_t length,
1357+
const CHARSET_INFO *from_cs,
1358+
const CHARSET_INFO *to_cs)
1359+
{
1360+
uint dummy_errors;
1361+
/* Calculate maxumum possible result length */
1362+
size_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
1363+
1364+
if (!m_thd->mysql) // bootstrap file handling
1365+
return 0;
1366+
1367+
if (conv_length > 250)
1368+
{
1369+
/*
1370+
For strings with conv_length greater than 250 bytes
1371+
we don't know how many bytes we will need to store length: one or two,
1372+
because we don't know result length until conversion is done.
1373+
For example, when converting from utf8 (mbmaxlen=3) to latin1,
1374+
conv_length=300 means that the result length can vary between 100 to 300.
1375+
length=100 needs one byte, length=300 needs to bytes.
1376+
1377+
Thus conversion directly to "packet" is not worthy.
1378+
Let's use "convert" as a temporary buffer.
1379+
*/
1380+
return (convert->copy((const char*)from, length, from_cs,
1381+
to_cs, &dummy_errors) ||
1382+
net_store_data((const uchar*)convert->ptr(), convert->length()));
1383+
}
1384+
size_t packet_length= packet->length();
1385+
size_t new_length= packet_length + conv_length + 1;
1386+
1387+
if (new_length > packet->alloced_length() && packet->mem_realloc(new_length))
1388+
return 1;
1389+
1390+
char *length_pos= (char*) packet->ptr() + packet_length;
1391+
char *to= length_pos + 1;
1392+
1393+
to+= length= copy_and_convert(to, conv_length, to_cs,
1394+
(const char*)from, length, from_cs,
1395+
&dummy_errors);
1396+
1397+
net_store_length((uchar*)length_pos, to - length_pos - 1);
1398+
packet->length((uint)(to - packet->ptr()));
1399+
if (next_mysql_field->max_length < length)
1400+
next_mysql_field->max_length= length;
1401+
++next_mysql_field;
1402+
return 0;
1403+
}
1404+
1405+
13131406
bool Protocol_classic::net_store_data(const uchar *from, size_t length)
13141407
{
13151408
char *field_buf;

sql/protocol_classic.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ static bool write_eof_packet(THD *, NET *, uint, uint);
4141

4242
#ifndef EMBEDDED_LIBRARY
4343
bool Protocol_classic::net_store_data(const uchar *from, size_t length)
44-
#else
45-
bool Protocol_binary::net_store_data(const uchar *from, size_t length)
46-
#endif
4744
{
4845
size_t packet_length=packet->length();
4946
/*
@@ -58,6 +55,7 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
5855
packet->length((uint) (to+length-(uchar *) packet->ptr()));
5956
return 0;
6057
}
58+
#endif
6159

6260

6361
/**
@@ -1552,6 +1550,7 @@ bool Protocol_binary::start_result_metadata(uint num_cols, uint flags,
15521550
}
15531551

15541552

1553+
#ifndef EMBEDDED_LIBRARY
15551554
void Protocol_binary::start_row()
15561555
{
15571556
if (send_metadata)
@@ -1560,6 +1559,7 @@ void Protocol_binary::start_row()
15601559
memset(const_cast<char*>(packet->ptr()), 0, 1+bit_fields);
15611560
field_pos=0;
15621561
}
1562+
#endif
15631563

15641564

15651565
bool Protocol_binary::store(const char *from, size_t length,

sql/protocol_classic.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ class Protocol_classic : public Protocol
5353
MEM_ROOT *field_alloc;
5454
virtual bool net_store_data(const uchar *from, size_t length);
5555
#endif
56-
bool net_store_data(const uchar *from, size_t length,
57-
const CHARSET_INFO *fromcs, const CHARSET_INFO *tocs);
56+
virtual bool net_store_data(const uchar *from, size_t length,
57+
const CHARSET_INFO *fromcs,
58+
const CHARSET_INFO *tocs);
5859
bool store_string_aux(const char *from, size_t length,
5960
const CHARSET_INFO *fromcs, const CHARSET_INFO *tocs);
6061

@@ -252,6 +253,9 @@ class Protocol_binary : public Protocol_text
252253
#ifdef EMBEDDED_LIBRARY
253254
virtual bool end_row();
254255
bool net_store_data(const uchar *from, size_t length);
256+
bool net_store_data(const uchar *from, size_t length,
257+
const CHARSET_INFO *fromcs,
258+
const CHARSET_INFO *tocs);
255259
#endif
256260
virtual bool store_null();
257261
virtual bool store_tiny(longlong from);

testclients/mysql_client_test.c

+47
Original file line numberDiff line numberDiff line change
@@ -20681,6 +20681,52 @@ static void test_wl8754()
2068120681
mysql_close(conn);
2068220682
}
2068320683

20684+
/*
20685+
BUG#17883203: MYSQL EMBEDDED MYSQL_STMT_EXECUTE RETURN
20686+
"MALFORMED COMMUNICATION PACKET" ERROR
20687+
*/
20688+
#define BUG17883203_STRING_SIZE 50
20689+
20690+
static void test_bug17883203()
20691+
{
20692+
MYSQL_STMT *stmt;
20693+
MYSQL_BIND bind;
20694+
char str_data[BUG17883203_STRING_SIZE];
20695+
my_bool is_null;
20696+
my_bool error;
20697+
unsigned long length;
20698+
const char stmt_text[] ="SELECT VERSION()";
20699+
int rc;
20700+
20701+
myheader("test_bug17883203");
20702+
20703+
stmt = mysql_stmt_init(mysql);
20704+
check_stmt(stmt);
20705+
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
20706+
check_execute(stmt, rc);
20707+
rc= mysql_stmt_execute(stmt);
20708+
check_execute(stmt, rc);
20709+
memset(&bind, 0, sizeof(bind));
20710+
20711+
bind.buffer_type= MYSQL_TYPE_STRING;
20712+
bind.buffer= (char *)str_data;
20713+
bind.buffer_length= BUG17883203_STRING_SIZE;
20714+
bind.is_null= &is_null;
20715+
bind.length= &length;
20716+
bind.error= &error;
20717+
20718+
rc= mysql_stmt_bind_result(stmt, &bind);
20719+
check_execute(stmt, rc);
20720+
rc= mysql_stmt_fetch(stmt);
20721+
check_execute(stmt, rc);
20722+
20723+
if (!opt_silent)
20724+
{
20725+
fprintf(stdout, "\n Version: %s", str_data);
20726+
}
20727+
mysql_stmt_close(stmt);
20728+
}
20729+
2068420730
static struct my_tests_st my_tests[]= {
2068520731
{ "disable_query_logs", disable_query_logs },
2068620732
{ "test_view_sp_list_fields", test_view_sp_list_fields },
@@ -20968,6 +21014,7 @@ static struct my_tests_st my_tests[]= {
2096821014
{ "test_bug21199582", test_bug21199582 },
2096921015
{ "test_bug20821550", test_bug20821550 },
2097021016
{ "test_wl8754", test_wl8754 },
21017+
{ "test_bug17883203", test_bug17883203 },
2097121018
{ 0, 0 }
2097221019
};
2097321020

0 commit comments

Comments
 (0)