Skip to content

Commit 06fb78c

Browse files
committed
MDEV-21995 Server crashes in Item_field::real_type_handler with table value constructor
1. Code simplification: Item_default_value handled all these values: a. DEFAULT(field) b. DEFAULT c. IGNORE and had various conditions to distinguish (a) from (b) and from (c). Introducing a new abstract class Item_contextually_typed_value_specification, to handle (b) and (c), so the hierarchy now looks as follows: Item Item_result_field Item_ident Item_field Item_default_value - DEFAULT(field) Item_contextually_typed_value_specification Item_default_specification - DEFAULT Item_ignore_specification - IGNORE 2. Introducing a new virtual method is_evaluable_expression() to determine if an Item is: - a normal expression, so its val_xxx()/get_date() methods can be called - or a just an expression substitute, whose value methods cannot be called. 3. Disallowing Items that are not evalualble expressions in table value constructors.
1 parent 4869e7f commit 06fb78c

File tree

8 files changed

+190
-106
lines changed

8 files changed

+190
-106
lines changed

mysql-test/main/table_value_constr.result

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,3 +2610,14 @@ $$
26102610
a
26112611
0
26122612
1
2613+
#
2614+
# MDEV-21995 Server crashes in Item_field::real_type_handler with table value constructor
2615+
#
2616+
VALUES (IGNORE);
2617+
ERROR HY000: 'ignore' is not allowed in this context
2618+
VALUES (DEFAULT);
2619+
ERROR HY000: 'default' is not allowed in this context
2620+
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
2621+
ERROR HY000: 'ignore' is not allowed in this context
2622+
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;
2623+
ERROR HY000: 'default' is not allowed in this context

mysql-test/main/table_value_constr.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,3 +1339,17 @@ BEGIN NOT ATOMIC
13391339
END;
13401340
$$
13411341
DELIMITER ;$$
1342+
1343+
1344+
--echo #
1345+
--echo # MDEV-21995 Server crashes in Item_field::real_type_handler with table value constructor
1346+
--echo #
1347+
1348+
--error ER_UNKNOWN_ERROR
1349+
VALUES (IGNORE);
1350+
--error ER_UNKNOWN_ERROR
1351+
VALUES (DEFAULT);
1352+
--error ER_UNKNOWN_ERROR
1353+
EXECUTE IMMEDIATE 'VALUES (?)' USING IGNORE;
1354+
--error ER_UNKNOWN_ERROR
1355+
EXECUTE IMMEDIATE 'VALUES (?)' USING DEFAULT;

sql/item.cc

Lines changed: 32 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ void item_init(void)
9999
}
100100

101101

102+
void Item::raise_error_not_evaluable()
103+
{
104+
Item::Print tmp(this, QT_ORDINARY);
105+
// TODO-10.5: add an error message to errmsg-utf8.txt
106+
my_printf_error(ER_UNKNOWN_ERROR,
107+
"'%s' is not allowed in this context", MYF(0), tmp.ptr());
108+
}
109+
110+
102111
void Item::push_note_converted_to_negative_complement(THD *thd)
103112
{
104113
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR,
@@ -4547,6 +4556,23 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
45474556
}
45484557

45494558

4559+
bool Item_param::is_evaluable_expression() const
4560+
{
4561+
switch (state) {
4562+
case SHORT_DATA_VALUE:
4563+
case LONG_DATA_VALUE:
4564+
case NULL_VALUE:
4565+
return true;
4566+
case NO_VALUE:
4567+
return true; // Not assigned yet, so we don't know
4568+
case IGNORE_VALUE:
4569+
case DEFAULT_VALUE:
4570+
break;
4571+
}
4572+
return false;
4573+
}
4574+
4575+
45504576
bool Item_param::can_return_value() const
45514577
{
45524578
// There's no "default". See comments in Item_param::save_in_field().
@@ -9308,12 +9334,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
93089334
Item_field *field_arg;
93099335
Field *def_field;
93109336
DBUG_ASSERT(fixed == 0);
9311-
9312-
if (!arg)
9313-
{
9314-
fixed= 1;
9315-
return FALSE;
9316-
}
9337+
DBUG_ASSERT(arg);
93179338

93189339
/*
93199340
DEFAULT() do not need table field so should not ask handler to bring
@@ -9389,11 +9410,7 @@ void Item_default_value::cleanup()
93899410

93909411
void Item_default_value::print(String *str, enum_query_type query_type)
93919412
{
9392-
if (!arg)
9393-
{
9394-
str->append(STRING_WITH_LEN("default"));
9395-
return;
9396-
}
9413+
DBUG_ASSERT(arg);
93979414
str->append(STRING_WITH_LEN("default("));
93989415
/*
93999416
We take DEFAULT from a field so do not need it value in case of const
@@ -9407,6 +9424,7 @@ void Item_default_value::print(String *str, enum_query_type query_type)
94079424

94089425
void Item_default_value::calculate()
94099426
{
9427+
DBUG_ASSERT(arg);
94109428
if (field->default_value)
94119429
field->set_default();
94129430
DEBUG_SYNC(field->table->in_use, "after_Item_default_value_calculate");
@@ -9450,14 +9468,8 @@ bool Item_default_value::send(Protocol *protocol, st_value *buffer)
94509468

94519469
int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
94529470
{
9453-
if (arg)
9454-
{
9455-
calculate();
9456-
return Item_field::save_in_field(field_arg, no_conversions);
9457-
}
9458-
9459-
return field_arg->save_in_field_default_value(context->error_processor ==
9460-
&view_error_processor);
9471+
calculate();
9472+
return Item_field::save_in_field(field_arg, no_conversions);
94619473
}
94629474

94639475
table_map Item_default_value::used_tables() const
@@ -9478,13 +9490,7 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer,
94789490
uchar *args)
94799491
{
94809492
DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare());
9481-
9482-
/*
9483-
If the value of arg is NULL, then this object represents a constant,
9484-
so further transformation is unnecessary (and impossible).
9485-
*/
9486-
if (!arg)
9487-
return 0;
9493+
DBUG_ASSERT(arg);
94889494

94899495
Item *new_item= arg->transform(thd, transformer, args);
94909496
if (!new_item)
@@ -9501,57 +9507,6 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer,
95019507
return (this->*transformer)(thd, args);
95029508
}
95039509

9504-
void Item_ignore_value::print(String *str, enum_query_type query_type)
9505-
{
9506-
str->append(STRING_WITH_LEN("ignore"));
9507-
}
9508-
9509-
int Item_ignore_value::save_in_field(Field *field_arg, bool no_conversions)
9510-
{
9511-
return field_arg->save_in_field_ignore_value(context->error_processor ==
9512-
&view_error_processor);
9513-
}
9514-
9515-
String *Item_ignore_value::val_str(String *str)
9516-
{
9517-
DBUG_ASSERT(0); // never should be called
9518-
null_value= 1;
9519-
return 0;
9520-
}
9521-
9522-
double Item_ignore_value::val_real()
9523-
{
9524-
DBUG_ASSERT(0); // never should be called
9525-
null_value= 1;
9526-
return 0.0;
9527-
}
9528-
9529-
longlong Item_ignore_value::val_int()
9530-
{
9531-
DBUG_ASSERT(0); // never should be called
9532-
null_value= 1;
9533-
return 0;
9534-
}
9535-
9536-
my_decimal *Item_ignore_value::val_decimal(my_decimal *decimal_value)
9537-
{
9538-
DBUG_ASSERT(0); // never should be called
9539-
null_value= 1;
9540-
return 0;
9541-
}
9542-
9543-
bool Item_ignore_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
9544-
{
9545-
DBUG_ASSERT(0); // never should be called
9546-
null_value= 1;
9547-
return TRUE;
9548-
}
9549-
9550-
bool Item_ignore_value::send(Protocol *protocol, st_value *buffer)
9551-
{
9552-
DBUG_ASSERT(0); // never should be called
9553-
return TRUE;
9554-
}
95559510

95569511
bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
95579512
{

0 commit comments

Comments
 (0)