mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fix stupid signed and unsigned conversion - When field and buffer types are different (Client receiving end)
Added tests for singed and unsigned conversion (client_test.c) tests/client_test.c: Tests for singed and unsigned conversion libmysql/libmysql.c: Fix signed and unsigned conversion - When field and buffer types are different
This commit is contained in:
@ -163,11 +163,6 @@ void STDCALL mysql_thread_end()
|
|||||||
#define reset_sigpipe(mysql)
|
#define reset_sigpipe(mysql)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define map_to_size(A,L) {\
|
|
||||||
char *tmp= (char *)&A;\
|
|
||||||
memset(tmp+L,0,8-L);\
|
|
||||||
}
|
|
||||||
|
|
||||||
static MYSQL* spawn_init(MYSQL* parent, const char* host,
|
static MYSQL* spawn_init(MYSQL* parent, const char* host,
|
||||||
unsigned int port,
|
unsigned int port,
|
||||||
const char* user,
|
const char* user,
|
||||||
@ -3967,6 +3962,7 @@ unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
|
|||||||
field->org_table= strdup_root(alloc,fields->org_table);
|
field->org_table= strdup_root(alloc,fields->org_table);
|
||||||
field->name = strdup_root(alloc,fields->name);
|
field->name = strdup_root(alloc,fields->name);
|
||||||
field->org_name = strdup_root(alloc,fields->org_name);
|
field->org_name = strdup_root(alloc,fields->org_name);
|
||||||
|
field->charsetnr= fields->charsetnr;
|
||||||
field->length = fields->length;
|
field->length = fields->length;
|
||||||
field->type = fields->type;
|
field->type = fields->type;
|
||||||
field->flags = fields->flags;
|
field->flags = fields->flags;
|
||||||
@ -4871,31 +4867,38 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
|
|||||||
|
|
||||||
|
|
||||||
/* Fetch data to buffers */
|
/* Fetch data to buffers */
|
||||||
static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row)
|
static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
|
||||||
|
my_bool field_is_unsigned)
|
||||||
{
|
{
|
||||||
ulong length;
|
ulong length;
|
||||||
|
|
||||||
switch (field_type) {
|
switch (field_type) {
|
||||||
case MYSQL_TYPE_TINY:
|
case MYSQL_TYPE_TINY:
|
||||||
{
|
{
|
||||||
longlong value= (longlong) **row;
|
char value= (char) **row;
|
||||||
map_to_size(value,(length= 1));
|
longlong data= (field_is_unsigned) ? (longlong) (unsigned char) value:
|
||||||
send_data_long(param,value);
|
(longlong) value;
|
||||||
|
send_data_long(param,data);
|
||||||
|
length= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_SHORT:
|
case MYSQL_TYPE_SHORT:
|
||||||
case MYSQL_TYPE_YEAR:
|
case MYSQL_TYPE_YEAR:
|
||||||
{
|
{
|
||||||
longlong value= (longlong)sint2korr(*row);
|
short value= sint2korr(*row);
|
||||||
map_to_size(value,(length= 2));
|
longlong data= (field_is_unsigned) ? (longlong) (unsigned short) value:
|
||||||
send_data_long(param, value);
|
(longlong) value;
|
||||||
|
send_data_long(param,data);
|
||||||
|
length= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_LONG:
|
case MYSQL_TYPE_LONG:
|
||||||
{
|
{
|
||||||
longlong value= (longlong)sint4korr(*row);
|
long value= sint4korr(*row);
|
||||||
map_to_size(value,(length= 4));
|
longlong data= (field_is_unsigned) ? (longlong) (unsigned long) value:
|
||||||
send_data_long(param,value);
|
(longlong) value;
|
||||||
|
send_data_long(param,data);
|
||||||
|
length= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MYSQL_TYPE_LONGLONG:
|
case MYSQL_TYPE_LONGLONG:
|
||||||
@ -5165,7 +5168,10 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
|
|||||||
if (field->type == bind->buffer_type)
|
if (field->type == bind->buffer_type)
|
||||||
(*bind->fetch_result)(bind, &row);
|
(*bind->fetch_result)(bind, &row);
|
||||||
else
|
else
|
||||||
fetch_results(bind, field->type, &row);
|
{
|
||||||
|
my_bool field_is_unsigned= (field->flags & UNSIGNED_FLAG) ? 1: 0;
|
||||||
|
fetch_results(bind, field->type, &row, field_is_unsigned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (! ((bit<<=1) & 255))
|
if (! ((bit<<=1) & 255))
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ static void client_connect()
|
|||||||
int rc;
|
int rc;
|
||||||
myheader_r("client_connect");
|
myheader_r("client_connect");
|
||||||
|
|
||||||
fprintf(stdout, "\n Establishig a connection ...");
|
fprintf(stdout, "\n Establishing a connection ...");
|
||||||
|
|
||||||
if (!(mysql = mysql_init(NULL)))
|
if (!(mysql = mysql_init(NULL)))
|
||||||
{
|
{
|
||||||
@ -5529,10 +5529,10 @@ static void test_ushort_bug()
|
|||||||
rc = mysql_fetch(stmt);
|
rc = mysql_fetch(stmt);
|
||||||
mystmt(stmt, rc);
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
fprintf(stdout,"\n ushort: %d (%ld)", short_value, s_length);
|
fprintf(stdout,"\n ushort : %d (%ld)", short_value, s_length);
|
||||||
fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length);
|
fprintf(stdout,"\n ulong : %ld (%ld)", long_value, l_length);
|
||||||
fprintf(stdout,"\n ulong : %lld (%ld)", longlong_value, ll_length);
|
fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
|
||||||
fprintf(stdout,"\n ulong : %d (%ld)", tiny_value, t_length);
|
fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
|
||||||
|
|
||||||
myassert(short_value == 35999);
|
myassert(short_value == 35999);
|
||||||
myassert(s_length == 2);
|
myassert(s_length == 2);
|
||||||
@ -5552,6 +5552,174 @@ static void test_ushort_bug()
|
|||||||
mysql_stmt_close(stmt);
|
mysql_stmt_close(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
To test a misc smallint-signed conversion bug
|
||||||
|
*/
|
||||||
|
static void test_sshort_bug()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND bind[4];
|
||||||
|
short short_value;
|
||||||
|
long long_value;
|
||||||
|
ulong s_length, l_length, ll_length, t_length;
|
||||||
|
ulonglong longlong_value;
|
||||||
|
int rc;
|
||||||
|
uchar tiny_value;
|
||||||
|
|
||||||
|
myheader("test_sshort_bug");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_sshort");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"CREATE TABLE test_sshort(a smallint signed, \
|
||||||
|
b smallint signed, \
|
||||||
|
c smallint unsigned, \
|
||||||
|
d smallint unsigned)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
|
||||||
|
stmt = mysql_prepare(mysql,"SELECT * FROM test_sshort",50);
|
||||||
|
mystmt_init(stmt);
|
||||||
|
|
||||||
|
rc = mysql_execute(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
bind[0].buffer_type= MYSQL_TYPE_SHORT;
|
||||||
|
bind[0].buffer= (char *)&short_value;
|
||||||
|
bind[0].is_null= 0;
|
||||||
|
bind[0].length= &s_length;
|
||||||
|
|
||||||
|
bind[1].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
bind[1].buffer= (char *)&long_value;
|
||||||
|
bind[1].is_null= 0;
|
||||||
|
bind[1].length= &l_length;
|
||||||
|
|
||||||
|
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
|
||||||
|
bind[2].buffer= (char *)&longlong_value;
|
||||||
|
bind[2].is_null= 0;
|
||||||
|
bind[2].length= &ll_length;
|
||||||
|
|
||||||
|
bind[3].buffer_type= MYSQL_TYPE_TINY;
|
||||||
|
bind[3].buffer= (char *)&tiny_value;
|
||||||
|
bind[3].is_null= 0;
|
||||||
|
bind[3].length= &t_length;
|
||||||
|
|
||||||
|
rc = mysql_bind_result(stmt, bind);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
rc = mysql_fetch(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
|
||||||
|
fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
|
||||||
|
fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
|
||||||
|
fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
|
||||||
|
|
||||||
|
myassert(short_value == -5999);
|
||||||
|
myassert(s_length == 2);
|
||||||
|
|
||||||
|
myassert(long_value == -5999);
|
||||||
|
myassert(l_length == 4);
|
||||||
|
|
||||||
|
myassert(longlong_value == 35999);
|
||||||
|
myassert(ll_length == 8);
|
||||||
|
|
||||||
|
myassert(tiny_value == 200);
|
||||||
|
myassert(t_length == 1);
|
||||||
|
|
||||||
|
rc = mysql_fetch(stmt);
|
||||||
|
myassert(rc == MYSQL_NO_DATA);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
To test a misc tinyint-signed conversion bug
|
||||||
|
*/
|
||||||
|
static void test_stiny_bug()
|
||||||
|
{
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND bind[4];
|
||||||
|
short short_value;
|
||||||
|
long long_value;
|
||||||
|
ulong s_length, l_length, ll_length, t_length;
|
||||||
|
ulonglong longlong_value;
|
||||||
|
int rc;
|
||||||
|
uchar tiny_value;
|
||||||
|
|
||||||
|
myheader("test_stiny_bug");
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_stiny");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"CREATE TABLE test_stiny(a tinyint signed, \
|
||||||
|
b tinyint signed, \
|
||||||
|
c tinyint unsigned, \
|
||||||
|
d tinyint unsigned)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
rc= mysql_query(mysql,"INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
|
||||||
|
myquery(rc);
|
||||||
|
|
||||||
|
|
||||||
|
stmt = mysql_prepare(mysql,"SELECT * FROM test_stiny",50);
|
||||||
|
mystmt_init(stmt);
|
||||||
|
|
||||||
|
rc = mysql_execute(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
bind[0].buffer_type= MYSQL_TYPE_SHORT;
|
||||||
|
bind[0].buffer= (char *)&short_value;
|
||||||
|
bind[0].is_null= 0;
|
||||||
|
bind[0].length= &s_length;
|
||||||
|
|
||||||
|
bind[1].buffer_type= MYSQL_TYPE_LONG;
|
||||||
|
bind[1].buffer= (char *)&long_value;
|
||||||
|
bind[1].is_null= 0;
|
||||||
|
bind[1].length= &l_length;
|
||||||
|
|
||||||
|
bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
|
||||||
|
bind[2].buffer= (char *)&longlong_value;
|
||||||
|
bind[2].is_null= 0;
|
||||||
|
bind[2].length= &ll_length;
|
||||||
|
|
||||||
|
bind[3].buffer_type= MYSQL_TYPE_TINY;
|
||||||
|
bind[3].buffer= (char *)&tiny_value;
|
||||||
|
bind[3].is_null= 0;
|
||||||
|
bind[3].length= &t_length;
|
||||||
|
|
||||||
|
rc = mysql_bind_result(stmt, bind);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
rc = mysql_fetch(stmt);
|
||||||
|
mystmt(stmt, rc);
|
||||||
|
|
||||||
|
fprintf(stdout,"\n sshort : %d (%ld)", short_value, s_length);
|
||||||
|
fprintf(stdout,"\n slong : %ld (%ld)", long_value, l_length);
|
||||||
|
fprintf(stdout,"\n longlong : %lld (%ld)", longlong_value, ll_length);
|
||||||
|
fprintf(stdout,"\n tinyint : %d (%ld)", tiny_value, t_length);
|
||||||
|
|
||||||
|
myassert(short_value == -128);
|
||||||
|
myassert(s_length == 2);
|
||||||
|
|
||||||
|
myassert(long_value == -127);
|
||||||
|
myassert(l_length == 4);
|
||||||
|
|
||||||
|
myassert(longlong_value == 255);
|
||||||
|
myassert(ll_length == 8);
|
||||||
|
|
||||||
|
myassert(tiny_value == 0);
|
||||||
|
myassert(t_length == 1);
|
||||||
|
|
||||||
|
rc = mysql_fetch(stmt);
|
||||||
|
myassert(rc == MYSQL_NO_DATA);
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read and parse arguments and MySQL options from my.cnf
|
Read and parse arguments and MySQL options from my.cnf
|
||||||
*/
|
*/
|
||||||
@ -5767,6 +5935,8 @@ int main(int argc, char **argv)
|
|||||||
test_pure_coverage(); /* keep pure coverage happy */
|
test_pure_coverage(); /* keep pure coverage happy */
|
||||||
test_buffers(); /* misc buffer handling */
|
test_buffers(); /* misc buffer handling */
|
||||||
test_ushort_bug(); /* test a simple conv bug from php */
|
test_ushort_bug(); /* test a simple conv bug from php */
|
||||||
|
test_sshort_bug(); /* test a simple conv bug from php */
|
||||||
|
test_stiny_bug(); /* test a simple conv bug from php */
|
||||||
|
|
||||||
end_time= time((time_t *)0);
|
end_time= time((time_t *)0);
|
||||||
total_time+= difftime(end_time, start_time);
|
total_time+= difftime(end_time, start_time);
|
||||||
|
Reference in New Issue
Block a user