summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2021-03-01 14:44:18 +0200
committerMonty <monty@mariadb.org>2021-03-01 22:09:05 +0200
commit415409579af68ee2e3c55d5294d7bb5e6397b03f (patch)
treeb60db15f52345496b34afd8288bd0a9f8b8119ba
parent6983ce704baff7a6e5dd411a289e3580bc7bea1a (diff)
downloadmariadb-git-415409579af68ee2e3c55d5294d7bb5e6397b03f.tar.gz
MDEV-24958 Server crashes in my_strtod ... with DEFAULT(blob)
Fixes also: MDEV-24942 Server crashes in _ma_rec_pack... with DEFAULT() on BLOB This was caused by two different bugs, both related to that the default value for the blob was not calculated before it was used: - There where now Item_default_value::..result() wrappers, which is needed as item in HAVING uses these. This causes crashes when using a reference to a DEFAULT(blob_field) in HAVING. It also caused wrong results when used with other fields with default value expressions that are not constants. - create_tmp_field() did not take into account that blob fields with default expressions are not yet initialized. Fixed by treating Item_default_value(blob) like a normal item expression.
-rw-r--r--mysql-test/main/having.result33
-rw-r--r--mysql-test/main/having.test20
-rw-r--r--sql/item.cc47
-rw-r--r--sql/item.h10
-rw-r--r--sql/sql_select.cc24
5 files changed, 129 insertions, 5 deletions
diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result
index f37cc48772e..233843de36f 100644
--- a/mysql-test/main/having.result
+++ b/mysql-test/main/having.result
@@ -846,3 +846,36 @@ t r
DROP TABLE t1;
DROP FUNCTION next_seq_value;
DROP TABLE series;
+#
+# MDEV-24958 Server crashes in my_strtod /
+# Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
+#
+# MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
+# DEFAULT() on BLOB
+#
+CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
+INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
+SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
+f
+foo
+bar
+SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
+h
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
+h
+A
+A
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
+h
+A
+A
+alter table t1 add column b int default (rand()+1+3);
+select default(b) AS h FROM t1 HAVING h > "2";
+h
+#
+#
+drop table t1;
diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test
index 179af14559f..8b0cc244f51 100644
--- a/mysql-test/main/having.test
+++ b/mysql-test/main/having.test
@@ -890,3 +890,23 @@ SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t)
DROP TABLE t1;
DROP FUNCTION next_seq_value;
DROP TABLE series;
+
+--echo #
+--echo # MDEV-24958 Server crashes in my_strtod /
+--echo # Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
+--echo #
+--echo # MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
+--echo # DEFAULT() on BLOB
+--echo #
+
+CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
+INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
+SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
+SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
+
+alter table t1 add column b int default (rand()+1+3);
+--replace_column 1 #
+select default(b) AS h FROM t1 HAVING h > "2";
+drop table t1;
diff --git a/sql/item.cc b/sql/item.cc
index 522fef57699..7b15c7ddb43 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9341,7 +9341,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
}
thd->column_usage= save_column_usage;
-
real_arg= arg->real_item();
if (real_arg->type() != FIELD_ITEM)
{
@@ -9364,7 +9363,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
def_field->reset_fields();
// If non-constant default value expression or a blob
if (def_field->default_value &&
- (def_field->default_value->flags || def_field->flags & BLOB_FLAG))
+ (def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
{
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
if (!newptr)
@@ -9461,11 +9460,53 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
return Item_field::save_in_field(field_arg, no_conversions);
}
+double Item_default_value::val_result()
+{
+ calculate();
+ return Item_field::val_result();
+}
+
+longlong Item_default_value::val_int_result()
+{
+ calculate();
+ return Item_field::val_int_result();
+}
+
+String *Item_default_value::str_result(String* tmp)
+{
+ calculate();
+ return Item_field::str_result(tmp);
+}
+
+bool Item_default_value::val_bool_result()
+{
+ calculate();
+ return Item_field::val_bool_result();
+}
+
+bool Item_default_value::is_null_result()
+{
+ calculate();
+ return Item_field::is_null_result();
+}
+
+my_decimal *Item_default_value::val_decimal_result(my_decimal *decimal_value)
+{
+ calculate();
+ return Item_field::val_decimal_result(decimal_value);
+}
+
+bool Item_default_value::get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate)
+{
+ calculate();
+ return Item_field::get_date_result(ltime, fuzzydate);
+}
+
table_map Item_default_value::used_tables() const
{
if (!field || !field->default_value)
return static_cast<table_map>(0);
- if (!field->default_value->expr) // not fully parsed field
+ if (!field->default_value->expr) // not fully parsed field
return static_cast<table_map>(RAND_TABLE_BIT);
return field->default_value->expr->used_tables();
}
diff --git a/sql/item.h b/sql/item.h
index 9200dd80ee8..9fa384f0947 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -5859,6 +5859,16 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
+
+ /* Result variants */
+ double val_result();
+ longlong val_int_result();
+ String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *val);
+ bool val_bool_result();
+ bool is_null_result();
+ bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate);
+
bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7658d843d8b..ce820946908 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -17224,7 +17224,13 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
the record in the original table.
If modify_item is 0 then fill_record() will update
the temporary table
-
+ @param table_cant_handle_bit_fields
+ Set to 1 if the temporary table cannot handle bit
+ fields. Only set for heap tables when the bit field
+ is part of an index.
+ @param make_copy_field
+ Set when using with rollup when we want to have
+ an exact copy of the field.
@retval
0 on error
@retval
@@ -17261,8 +17267,22 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return result;
}
- case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM:
+ {
+ Field *field= ((Item_default_value*) item)->field;
+ if (field->default_value && (field->flags & BLOB_FLAG))
+ {
+ /*
+ We have to use a copy function when using a blob with default value
+ as the we have to calcuate the default value before we can use it.
+ */
+ return create_tmp_field_from_item(thd, item, table,
+ (make_copy_field ? 0 : copy_func),
+ modify_item);
+ }
+ }
+ /* Fall through */
+ case Item::FIELD_ITEM:
case Item::CONTEXTUALLY_TYPED_VALUE_ITEM:
case Item::INSERT_VALUE_ITEM:
case Item::TRIGGER_FIELD_ITEM: