mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-20261 NULL passed to String::eq, SEGV, server crash, regression in 10.4
Type_handler_xxx::Item_const_eq() can handle only non-NULL values. The code in Item_basic_value::eq() did not take this into account. Adding a test to detect three different combinations: - Both values are NULLs, return true. - Only one value is NULL, return false. - Both values are not NULL, call Type_handler::Item_const_eq() to check equality.
This commit is contained in:
parent
db537a8372
commit
9f20968169
2 changed files with 62 additions and 2 deletions
16
sql/item.cc
16
sql/item.cc
|
@ -3477,8 +3477,20 @@ bool Item_basic_value::eq(const Item *item, bool binary_cmp) const
|
|||
(h0= type_handler())->type_handler_for_comparison() ==
|
||||
(h1= item->type_handler())->type_handler_for_comparison() &&
|
||||
h0->cast_to_int_type_handler()->type_handler_for_comparison() ==
|
||||
h1->cast_to_int_type_handler()->type_handler_for_comparison() &&
|
||||
h0->Item_const_eq(c0, c1, binary_cmp);
|
||||
h1->cast_to_int_type_handler()->type_handler_for_comparison();
|
||||
if (res)
|
||||
{
|
||||
switch (c0->const_is_null() + c1->const_is_null()) {
|
||||
case 2: // Two NULLs
|
||||
res= true;
|
||||
break;
|
||||
case 1: // NULL and non-NULL
|
||||
res= false;
|
||||
break;
|
||||
case 0: // Two non-NULLs
|
||||
res= h0->Item_const_eq(c0, c1, binary_cmp);
|
||||
}
|
||||
}
|
||||
DBUG_EXECUTE_IF("Item_basic_value",
|
||||
push_warning_printf(current_thd,
|
||||
Sql_condition::WARN_LEVEL_NOTE,
|
||||
|
|
|
@ -20886,6 +20886,53 @@ static void test_explain_meta()
|
|||
mct_close_log();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDEV-20261 NULL passed to String::eq, SEGV, server crash, regression in 10.4
|
||||
*/
|
||||
static void test_mdev20261()
|
||||
{
|
||||
int rc;
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND param[1];
|
||||
const char *query= "SELECT * FROM t1 WHERE f = ? OR f = 'foo'";
|
||||
char val[]= "";
|
||||
my_bool is_null= TRUE;
|
||||
|
||||
myheader("test_mdev20261");
|
||||
|
||||
rc= mysql_query(mysql, "CREATE OR REPLACE TABLE t1 (f varchar(64)) ENGINE=MyISAM");
|
||||
myquery(rc);
|
||||
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
check_stmt(stmt);
|
||||
rc= mysql_stmt_prepare(stmt, query, strlen(query));
|
||||
check_execute(stmt, rc);
|
||||
|
||||
verify_param_count(stmt, 1);
|
||||
|
||||
bzero((char*) param, sizeof(param));
|
||||
|
||||
param[0].buffer= &val;
|
||||
param[0].buffer_type= MYSQL_TYPE_STRING;
|
||||
param[0].is_null= &is_null;
|
||||
|
||||
rc= mysql_stmt_bind_param(stmt, param);
|
||||
check_execute(stmt, rc);
|
||||
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
check_execute(stmt, rc);
|
||||
|
||||
rc= mysql_stmt_store_result(stmt);
|
||||
check_execute(stmt, rc);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
|
||||
rc= mysql_query(mysql, "DROP TABLE t1");
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
static struct my_tests_st my_tests[]= {
|
||||
{ "disable_query_logs", disable_query_logs },
|
||||
{ "test_view_sp_list_fields", test_view_sp_list_fields },
|
||||
|
@ -21179,6 +21226,7 @@ static struct my_tests_st my_tests[]= {
|
|||
#endif
|
||||
{ "test_explain_meta", test_explain_meta },
|
||||
{ "test_mdev18408", test_mdev18408 },
|
||||
{ "test_mdev20261", test_mdev20261 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue