Commit e164c08e authored by unknown's avatar unknown

Bug #28934: server crash when receiving malformed com_execute packets

 Sometimes a parameter slot may not get a value because of the protocol
 data being plain wrong.
 Such cases should be detected and handled by returning an error.
 Fixed by checking data stream constraints where possible (like maximum
 length) and reacting to the case where a value cannot be constructed.


sql/sql_prepare.cc:
  Bug #28934: 
   - check for a parameter slot not being set because 
      of wrong data
   - check if the length read from the stream is not
      greater than the maximum length of the field
tests/mysql_client_test.c:
  Bug #28934: test case
parent 59d139eb
...@@ -562,6 +562,8 @@ void set_param_date(Item_param *param, uchar **pos, ulong len) ...@@ -562,6 +562,8 @@ void set_param_date(Item_param *param, uchar **pos, ulong len)
static void set_param_str(Item_param *param, uchar **pos, ulong len) static void set_param_str(Item_param *param, uchar **pos, ulong len)
{ {
ulong length= get_param_length(pos, len); ulong length= get_param_length(pos, len);
if (length > len)
length= len;
param->set_str((const char *)*pos, length); param->set_str((const char *)*pos, length);
*pos+= length; *pos+= length;
} }
...@@ -731,6 +733,8 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, ...@@ -731,6 +733,8 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
if (read_pos >= data_end) if (read_pos >= data_end)
DBUG_RETURN(1); DBUG_RETURN(1);
param->set_param_func(param, &read_pos, data_end - read_pos); param->set_param_func(param, &read_pos, data_end - read_pos);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
} }
} }
res= param->query_val_str(&str); res= param->query_val_str(&str);
...@@ -767,6 +771,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, ...@@ -767,6 +771,8 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
if (read_pos >= data_end) if (read_pos >= data_end)
DBUG_RETURN(1); DBUG_RETURN(1);
param->set_param_func(param, &read_pos, data_end - read_pos); param->set_param_func(param, &read_pos, data_end - read_pos);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
} }
} }
if (param->convert_str_value(stmt->thd)) if (param->convert_str_value(stmt->thd))
...@@ -849,6 +855,8 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query) ...@@ -849,6 +855,8 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query)
client_param->length ? client_param->length ?
*client_param->length : *client_param->length :
client_param->buffer_length); client_param->buffer_length);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
} }
} }
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
...@@ -890,6 +898,8 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query) ...@@ -890,6 +898,8 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
client_param->length ? client_param->length ?
*client_param->length : *client_param->length :
client_param->buffer_length); client_param->buffer_length);
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
} }
} }
res= param->query_val_str(&str); res= param->query_val_str(&str);
......
...@@ -15686,6 +15686,88 @@ end: ...@@ -15686,6 +15686,88 @@ end:
} }
/*
Bug#28934: server crash when receiving malformed com_execute packets
*/
static void test_bug28934()
{
MYSQL *l_mysql;
my_bool error= 0;
my_ulonglong res;
MYSQL_BIND bind[5];
MYSQL_STMT *stmt;
int cnt;
if (!(l_mysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
DIE_UNLESS(1);
}
if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket, CLIENT_FOUND_ROWS)))
{
myerror("connection failed");
error= 1;
goto end;
}
l_mysql->reconnect= 1;
if (mysql_query(l_mysql, "drop table if exists t1"))
{
myerror(NULL);
error= 1;
goto end;
}
if (mysql_query(l_mysql, "create table t1(id int)"))
{
myerror(NULL);
error= 1;
goto end;
}
if (mysql_query(l_mysql, "insert into t1 values(1),(2),(3),(4),(5)"))
{
myerror(NULL);
error= 1;
goto end;
}
if (!(stmt= mysql_simple_prepare(l_mysql,
"select * from t1 where id in(?,?,?,?,?)")))
{
myerror(NULL);
error= 1;
goto end;
}
memset (&bind, 0, sizeof (bind));
for (cnt= 0; cnt < 5; cnt++)
{
bind[cnt].buffer_type= MYSQL_TYPE_LONG;
bind[cnt].buffer= (char*)&cnt;
bind[cnt].buffer_length= 0;
}
if(mysql_stmt_bind_param(stmt, bind))
{
myerror(NULL);
error= 1;
goto end;
}
stmt->param_count=2;
error= mysql_stmt_execute(stmt);
DIE_UNLESS (error != 0);
myerror(NULL);
error= 0;
if (mysql_query(l_mysql, "drop table t1"))
{
myerror(NULL);
error= 1;
}
end:
mysql_close(l_mysql);
DIE_UNLESS(error == 0);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -15968,6 +16050,7 @@ static struct my_tests_st my_tests[]= { ...@@ -15968,6 +16050,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug24179", test_bug24179 }, { "test_bug24179", test_bug24179 },
{ "test_bug27876", test_bug27876 }, { "test_bug27876", test_bug27876 },
{ "test_bug28505", test_bug28505 }, { "test_bug28505", test_bug28505 },
{ "test_bug28934", test_bug28934 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment