summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2018-05-16 09:44:22 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2018-05-16 09:44:22 +0400
commita639eff5940ed4147709511aeaee922fa7095284 (patch)
tree7d8faf3e9668d27904fc37b18a701ef9155f1b54
parentcd15e764a8a4f3e799f1efaede413c95e3233df6 (diff)
downloadmariadb-git-a639eff5940ed4147709511aeaee922fa7095284.tar.gz
MDEV-15813 ASAN use-after-poison in hp_hashnr upon HANDLER READ on a versioned HEAP table.
Check index capabilities before executing HANDLER READ command.
-rw-r--r--mysql-test/suite/handler/heap.result21
-rw-r--r--mysql-test/suite/handler/heap.test20
-rw-r--r--mysql-test/suite/handler/interface.result22
-rw-r--r--mysql-test/suite/handler/interface.test25
-rw-r--r--mysql-test/suite/innodb_fts/r/innodb_fts_misc.result2
-rw-r--r--mysql-test/suite/innodb_fts/t/innodb_fts_misc.test1
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/sql_handler.cc33
-rw-r--r--sql/sql_handler.h3
-rw-r--r--sql/sql_prepare.cc1
10 files changed, 122 insertions, 8 deletions
diff --git a/mysql-test/suite/handler/heap.result b/mysql-test/suite/handler/heap.result
index fc42e43f710..9679b48a367 100644
--- a/mysql-test/suite/handler/heap.result
+++ b/mysql-test/suite/handler/heap.result
@@ -1738,7 +1738,7 @@ connection default;
CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree(a, b)) engine=memory;
INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
HANDLER t1 OPEN;
-HANDLER t1 READ a>=(2) limit 3;
+HANDLER t1 READ a=(2) limit 3;
a b
2 20
2 20
@@ -1841,3 +1841,22 @@ ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this op
HANDLER t1 CLOSE;
DROP TABLE t1;
End of 5.3 tests
+#
+# MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+# HANDLER READ on a versioned HEAP table
+#
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP;
+INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40);
+HANDLER t1 OPEN AS m;
+HANDLER m READ `PRIMARY`= (3,30);
+a b
+3 30
+HANDLER m READ `PRIMARY`> (3,30);
+ERROR HY000: HASH index `PRIMARY` does not support this operation
+HANDLER m READ `ba`= (30,3);
+a b
+3 30
+HANDLER m READ `ba`= (30);
+ERROR HY000: HASH index `ba` does not support this operation
+HANDLER m CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/heap.test b/mysql-test/suite/handler/heap.test
index bc070cf743f..d60f92daa76 100644
--- a/mysql-test/suite/handler/heap.test
+++ b/mysql-test/suite/handler/heap.test
@@ -18,7 +18,7 @@ CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree(
INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
HANDLER t1 OPEN;
-HANDLER t1 READ a>=(2) limit 3;
+HANDLER t1 READ a=(2) limit 3;
HANDLER t1 READ a PREV;
HANDLER t1 READ a PREV;
HANDLER t1 READ a PREV;
@@ -85,3 +85,21 @@ HANDLER t1 CLOSE;
DROP TABLE t1;
--echo End of 5.3 tests
+
+--echo #
+--echo # MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+--echo # HANDLER READ on a versioned HEAP table
+--echo #
+
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP;
+INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40);
+HANDLER t1 OPEN AS m;
+HANDLER m READ `PRIMARY`= (3,30);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER m READ `PRIMARY`> (3,30);
+HANDLER m READ `ba`= (30,3);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER m READ `ba`= (30);
+HANDLER m CLOSE;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result
index a4ac32c16b4..c4a169be185 100644
--- a/mysql-test/suite/handler/interface.result
+++ b/mysql-test/suite/handler/interface.result
@@ -312,3 +312,25 @@ Note 1050 Table 'v' already exists
handler v read next;
ERROR 42S02: Unknown table 'v' in HANDLER
drop view v;
+#
+# MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+# HANDLER READ on a versioned HEAP table
+#
+CREATE TABLE t1 (g GEOMETRY NOT NULL, SPATIAL gi(g));
+INSERT INTO t1 VALUES (POINT(0,0));
+HANDLER t1 OPEN AS h;
+HANDLER h READ `gi`= (10);
+ERROR HY000: SPATIAL index `gi` does not support this operation
+HANDLER h READ `gi`> (10);
+ERROR HY000: SPATIAL index `gi` does not support this operation
+HANDLER h CLOSE;
+DROP TABLE t1;
+CREATE TABLE t1 (w VARCHAR(100), FULLTEXT fk(w));
+INSERT INTO t1 VALUES ('one two three');
+HANDLER t1 OPEN AS h;
+HANDLER h READ `fk`= (10);
+ERROR HY000: FULLTEXT index `fk` does not support this operation
+HANDLER h READ `fk`> (10);
+ERROR HY000: FULLTEXT index `fk` does not support this operation
+HANDLER h CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test
index 2f576c9b291..15853dfdbf5 100644
--- a/mysql-test/suite/handler/interface.test
+++ b/mysql-test/suite/handler/interface.test
@@ -354,3 +354,28 @@ execute stmt;
--error ER_UNKNOWN_TABLE
handler v read next;
drop view v;
+
+--echo #
+--echo # MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+--echo # HANDLER READ on a versioned HEAP table
+--echo #
+
+CREATE TABLE t1 (g GEOMETRY NOT NULL, SPATIAL gi(g));
+INSERT INTO t1 VALUES (POINT(0,0));
+HANDLER t1 OPEN AS h;
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `gi`= (10);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `gi`> (10);
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (w VARCHAR(100), FULLTEXT fk(w));
+INSERT INTO t1 VALUES ('one two three');
+HANDLER t1 OPEN AS h;
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `fk`= (10);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `fk`> (10);
+HANDLER h CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result
index ac8fcd1e26d..1322867551f 100644
--- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result
+++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result
@@ -688,7 +688,7 @@ INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
CREATE FULLTEXT INDEX i ON t1 (char_column);
HANDLER t1 OPEN;
HANDLER t1 READ i = ('aaa');
-id char_column
+ERROR HY000: FULLTEXT index `i` does not support this operation
DROP TABLE t1;
"----------Test25---------"
CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_CROATIAN_CI) ENGINE=InnoDB;
diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test
index 68ca8974512..150d632b26f 100644
--- a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test
+++ b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test
@@ -648,6 +648,7 @@ CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE =
INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
CREATE FULLTEXT INDEX i ON t1 (char_column);
HANDLER t1 OPEN;
+--error ER_KEY_DOESNT_SUPPORT
HANDLER t1 READ i = ('aaa');
DROP TABLE t1;
#23. Duplicate key error when there are no unique indexes (procedure test)
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 4d1d73997af..77347472521 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7917,3 +7917,5 @@ ER_EMPTY_ROW_IN_TVC
eng "Row with no elements is not allowed in table value constructor in this context"
ER_VERS_QUERY_IN_PARTITION
eng "SYSTEM_TIME partitions in table %`s does not support historical query"
+ER_KEY_DOESNT_SUPPORT
+ eng "%s index %`s does not support this operation"
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 187a7462c87..02d5bbfc84f 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -618,7 +618,7 @@ static SQL_HANDLER *mysql_ha_find_handler(THD *thd, const LEX_CSTRING *name)
static bool
mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
enum enum_ha_read_modes mode, const char *keyname,
- List<Item> *key_expr,
+ List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode,
Item *cond, bool in_prepare)
{
THD *thd= handler->thd;
@@ -660,6 +660,18 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
Item *item;
key_part_map keypart_map;
uint key_len;
+ const KEY *c_key= table->s->key_info + handler->keyno;
+
+ if ((c_key->flags & HA_SPATIAL) ||
+ c_key->algorithm == HA_KEY_ALG_FULLTEXT ||
+ (ha_rkey_mode != HA_READ_KEY_EXACT &&
+ (table->file->index_flags(handler->keyno, 0, TRUE) &
+ (HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE)) == 0))
+ {
+ my_error(ER_KEY_DOESNT_SUPPORT, MYF(0),
+ table->file->index_type(handler->keyno), keyinfo->name);
+ return 1;
+ }
if (key_expr->elements > keyinfo->user_defined_key_parts)
{
@@ -667,6 +679,16 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
keyinfo->user_defined_key_parts);
return 1;
}
+
+ if (key_expr->elements < keyinfo->user_defined_key_parts &&
+ (table->file->index_flags(handler->keyno, 0, TRUE) &
+ HA_ONLY_WHOLE_INDEX))
+ {
+ my_error(ER_KEY_DOESNT_SUPPORT, MYF(0),
+ table->file->index_type(handler->keyno), keyinfo->name);
+ return 1;
+ }
+
for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)
{
my_bitmap_map *old_map;
@@ -841,7 +863,8 @@ retry:
goto err0; // mysql_lock_tables() printed error message already
}
- if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, cond, 0))
+ if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr,
+ ha_rkey_mode, cond, 0))
goto err;
mode= handler->mode;
keyno= handler->keyno;
@@ -1000,14 +1023,16 @@ err0:
SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode,
const char *keyname,
- List<Item> *key_expr, Item *cond)
+ List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode,
+ Item *cond)
{
SQL_HANDLER *handler;
DBUG_ENTER("mysql_ha_read_prepare");
if (!(handler= mysql_ha_find_handler(thd, &tables->alias)))
DBUG_RETURN(0);
tables->table= handler->table; // This is used by fix_fields
- if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr, cond, 1))
+ if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr,
+ ha_rkey_mode, cond, 1))
DBUG_RETURN(0);
DBUG_RETURN(handler);
}
diff --git a/sql/sql_handler.h b/sql/sql_handler.h
index ffefec91fad..4c16f7e5c57 100644
--- a/sql/sql_handler.h
+++ b/sql/sql_handler.h
@@ -80,5 +80,6 @@ void mysql_ha_rm_temporary_tables(THD *thd);
SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode,
const char *keyname,
- List<Item> *key_expr, Item *cond);
+ List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode,
+ Item *cond);
#endif
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b149727484d..2b5bac87835 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2204,6 +2204,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt,
if (!(ha_table= mysql_ha_read_prepare(thd, tables, lex->ha_read_mode,
lex->ident.str,
lex->insert_list,
+ lex->ha_rkey_mode,
lex->select_lex.where)))
DBUG_RETURN(1);