summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavi Arnaut <Davi.Arnaut@Sun.COM>2010-06-28 12:21:28 -0300
committerDavi Arnaut <Davi.Arnaut@Sun.COM>2010-06-28 12:21:28 -0300
commit07767edcce4709b42bae5d3d9ca7be9ceacb95da (patch)
tree3dd60cea96ac5885f0651a8e47675e55346ed5c2
parentd4c4bd6e2f75677161e005ba161d2d01e2cbdf19 (diff)
downloadmariadb-git-07767edcce4709b42bae5d3d9ca7be9ceacb95da.tar.gz
Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run
The problem was that a user could supply supply data in chunks via the COM_STMT_SEND_LONG_DATA command to prepared statement parameter other than of type TEXT or BLOB. This posed a problem since other parameter types aren't setup to handle long data, which would lead to a crash when attempting to use the supplied data. Given that long data can be supplied at any stage of a prepared statement, coupled with the fact that the type of a parameter marker might change between consecutive executions, the solution is to validate at execution time each parameter marker for which a data stream was provided. If the parameter type is not TEXT or BLOB (that is, if the type is not able to handle a data stream), a error is returned.
-rw-r--r--sql/sql_prepare.cc28
-rw-r--r--tests/mysql_client_test.c58
2 files changed, 86 insertions, 0 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 06f77f9689c..c2fecd63777 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -674,6 +674,18 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
}
#ifndef EMBEDDED_LIBRARY
+
+/**
+ Check whether this parameter data type is compatible with long data.
+ Used to detect whether a long data stream has been supplied to a
+ incompatible data type.
+*/
+inline bool is_param_long_data_type(Item_param *param)
+{
+ return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) &&
+ (param->param_type <= MYSQL_TYPE_STRING));
+}
+
/*
Routines to assign parameters from data supplied by the client.
@@ -737,6 +749,14 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
DBUG_RETURN(1);
}
}
+ /*
+ A long data stream was supplied for this parameter marker.
+ This was done after prepare, prior to providing a placeholder
+ type (the types are supplied at execute). Check that the
+ supplied type of placeholder can accept a data stream.
+ */
+ else if (!is_param_long_data_type(param))
+ DBUG_RETURN(1);
res= param->query_val_str(&str);
if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */
@@ -775,6 +795,14 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
DBUG_RETURN(1);
}
}
+ /*
+ A long data stream was supplied for this parameter marker.
+ This was done after prepare, prior to providing a placeholder
+ type (the types are supplied at execute). Check that the
+ supplied type of placeholder can accept a data stream.
+ */
+ else if (is_param_long_data_type(param))
+ DBUG_RETURN(1);
if (param->convert_str_value(stmt->thd))
DBUG_RETURN(1); /* out of memory */
}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index b50c1efe92b..43a418c8300 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -16757,6 +16757,63 @@ static void test_bug53907()
}
+/**
+ Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run
+*/
+
+static void test_bug54041()
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind;
+
+ DBUG_ENTER("test_bug54041");
+ myheader("test_bug54041");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (a) VALUES (?)");
+ check_stmt(stmt);
+ verify_param_count(stmt, 1);
+
+ memset(&bind, 0, sizeof(bind));
+
+ /* Any type that does not support long data handling. */
+ bind.buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_bind_param(stmt, &bind);
+ check_execute(stmt, rc);
+
+ /*
+ Trick the client API into sending a long data packet for
+ the parameter. Long data is only supported for string and
+ binary types.
+ */
+ stmt->params[0].buffer_type= MYSQL_TYPE_STRING;
+
+ rc= mysql_stmt_send_long_data(stmt, 0, "data", 5);
+ check_execute(stmt, rc);
+
+ /* Undo API violation. */
+ stmt->params[0].buffer_type= MYSQL_TYPE_LONG;
+
+ rc= mysql_stmt_execute(stmt);
+ /* Incorrect arguments. */
+ check_execute_r(stmt, rc);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ DBUG_VOID_RETURN;
+}
+
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -17062,6 +17119,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug45010", test_bug45010 },
{ "test_bug53371", test_bug53371 },
{ "test_bug53907", test_bug53907 },
+ { "test_bug54041", test_bug54041 },
{ 0, 0 }
};