From 279b50b4eb69f882510f069e79715c38dc13355e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 22 Apr 2019 14:01:58 +0400 Subject: MDEV-14041 Server crashes in String::length on queries with functions and ROLLUP --- mysql-test/r/olap.result | 40 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/olap.test | 22 ++++++++++++++++++++++ sql/item.h | 39 +++++++++++++++++++++++++++++++++++++++ sql/item_func.h | 11 +++++++---- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 84c54c0c3c7..df2d6416648 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -800,5 +800,45 @@ latin1 binary DROP TABLE t; # +# MDEV-14041 Server crashes in String::length on queries with functions and ROLLUP +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT GET_LOCK( 'foo', 0 ); +GET_LOCK( 'foo', 0 ) +1 +SELECT HEX( RELEASE_LOCK( 'foo' ) ) AS f FROM t1 GROUP BY f WITH ROLLUP; +f +NULL +1 +NULL +DROP TABLE t1; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT i FROM t1 GROUP BY i WITH ROLLUP +UNION ALL +SELECT ELT( FOUND_ROWS(), 1 ) f FROM t1 GROUP BY f WITH ROLLUP; +i +1 +2 +NULL +NULL +NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +SELECT a FROM t1 GROUP BY NULLIF( CONVERT('', DATE), '2015-10-15' ) WITH ROLLUP; +a +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +Warning 1292 Incorrect datetime value: '' +Warning 1292 Incorrect datetime value: '' +Warning 1292 Incorrect datetime value: '' +Warning 1292 Incorrect datetime value: '' +Warning 1292 Incorrect datetime value: '' +DROP TABLE t1; +# # End of 10.1 tests # diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index bb7806969d3..8d1951573b3 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -439,6 +439,28 @@ SELECT CHARSET(d) AS f FROM t GROUP BY d WITH ROLLUP; DROP TABLE t; +--echo # +--echo # MDEV-14041 Server crashes in String::length on queries with functions and ROLLUP +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT GET_LOCK( 'foo', 0 ); +SELECT HEX( RELEASE_LOCK( 'foo' ) ) AS f FROM t1 GROUP BY f WITH ROLLUP; +DROP TABLE t1; + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT i FROM t1 GROUP BY i WITH ROLLUP +UNION ALL +SELECT ELT( FOUND_ROWS(), 1 ) f FROM t1 GROUP BY f WITH ROLLUP; +DROP TABLE t1; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +SELECT a FROM t1 GROUP BY NULLIF( CONVERT('', DATE), '2015-10-15' ) WITH ROLLUP; +DROP TABLE t1; + --echo # --echo # End of 10.1 tests --echo # diff --git a/sql/item.h b/sql/item.h index 4b93d3f9164..5c432887ed9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -663,6 +663,45 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); + /* Helper methods, to get an Item value from another Item */ + double val_real_from_item(Item *item) + { + DBUG_ASSERT(fixed == 1); + double value= item->val_real(); + null_value= item->null_value; + return value; + } + longlong val_int_from_item(Item *item) + { + DBUG_ASSERT(fixed == 1); + longlong value= item->val_int(); + null_value= item->null_value; + return value; + } + String *val_str_from_item(Item *item, String *str) + { + DBUG_ASSERT(fixed == 1); + String *res= item->val_str(str); + if (res) + res->set_charset(collation.collation); + if ((null_value= item->null_value)) + res= NULL; + return res; + } + my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value) + { + DBUG_ASSERT(fixed == 1); + my_decimal *value= item->val_decimal(decimal_value); + if ((null_value= item->null_value)) + value= NULL; + return value; + } + bool get_date_from_item(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) + { + bool rc= item->get_date(ltime, fuzzydate); + null_value= MY_TEST(rc || item->null_value); + return rc; + } /* This method is used if the item was not null but convertion to TIME/DATE/DATETIME failed. We return a zero date if allowed, diff --git a/sql/item_func.h b/sql/item_func.h index 9700429d543..36a2f94b31d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1120,10 +1120,13 @@ public: name= a->name; name_length= a->name_length; } - double val_real() { return args[0]->val_real(); } - longlong val_int() { return args[0]->val_int(); } - String *val_str(String *str) { return args[0]->val_str(str); } - my_decimal *val_decimal(my_decimal *dec) { return args[0]->val_decimal(dec); } + double val_real() { return val_real_from_item(args[0]); } + longlong val_int() { return val_int_from_item(args[0]); } + String *val_str(String *str) { return val_str_from_item(args[0], str); } + my_decimal *val_decimal(my_decimal *dec) + { return val_decimal_from_item(args[0], dec); } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_item(args[0], ltime, fuzzydate); } const char *func_name() const { return "rollup_const"; } bool const_item() const { return 0; } Item_result result_type() const { return args[0]->result_type(); } -- cgit v1.2.1