Commit a639eff5 authored by Alexey Botchkov's avatar Alexey Botchkov

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.
parent cd15e764
...@@ -1738,7 +1738,7 @@ connection default; ...@@ -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; 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); INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
HANDLER t1 OPEN; HANDLER t1 OPEN;
HANDLER t1 READ a>=(2) limit 3; HANDLER t1 READ a=(2) limit 3;
a b a b
2 20 2 20
2 20 2 20
...@@ -1841,3 +1841,22 @@ ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this op ...@@ -1841,3 +1841,22 @@ ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this op
HANDLER t1 CLOSE; HANDLER t1 CLOSE;
DROP TABLE t1; DROP TABLE t1;
End of 5.3 tests 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;
...@@ -18,7 +18,7 @@ CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree( ...@@ -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); INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
HANDLER t1 OPEN; 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; HANDLER t1 READ a PREV;
HANDLER t1 READ a PREV; HANDLER t1 READ a PREV;
...@@ -85,3 +85,21 @@ HANDLER t1 CLOSE; ...@@ -85,3 +85,21 @@ HANDLER t1 CLOSE;
DROP TABLE t1; DROP TABLE t1;
--echo End of 5.3 tests --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;
...@@ -312,3 +312,25 @@ Note 1050 Table 'v' already exists ...@@ -312,3 +312,25 @@ Note 1050 Table 'v' already exists
handler v read next; handler v read next;
ERROR 42S02: Unknown table 'v' in HANDLER ERROR 42S02: Unknown table 'v' in HANDLER
drop view v; 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;
...@@ -354,3 +354,28 @@ execute stmt; ...@@ -354,3 +354,28 @@ execute stmt;
--error ER_UNKNOWN_TABLE --error ER_UNKNOWN_TABLE
handler v read next; handler v read next;
drop view v; 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;
...@@ -688,7 +688,7 @@ INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc'); ...@@ -688,7 +688,7 @@ INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
CREATE FULLTEXT INDEX i ON t1 (char_column); CREATE FULLTEXT INDEX i ON t1 (char_column);
HANDLER t1 OPEN; HANDLER t1 OPEN;
HANDLER t1 READ i = ('aaa'); HANDLER t1 READ i = ('aaa');
id char_column ERROR HY000: FULLTEXT index `i` does not support this operation
DROP TABLE t1; DROP TABLE t1;
"----------Test25---------" "----------Test25---------"
CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_CROATIAN_CI) ENGINE=InnoDB; CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8 COLLATE UTF8_CROATIAN_CI) ENGINE=InnoDB;
......
...@@ -648,6 +648,7 @@ CREATE TABLE t1 ( id INT , char_column VARCHAR(60) CHARACTER SET UTF8) ENGINE = ...@@ -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'); INSERT INTO t1 VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
CREATE FULLTEXT INDEX i ON t1 (char_column); CREATE FULLTEXT INDEX i ON t1 (char_column);
HANDLER t1 OPEN; HANDLER t1 OPEN;
--error ER_KEY_DOESNT_SUPPORT
HANDLER t1 READ i = ('aaa'); HANDLER t1 READ i = ('aaa');
DROP TABLE t1; DROP TABLE t1;
#23. Duplicate key error when there are no unique indexes (procedure test) #23. Duplicate key error when there are no unique indexes (procedure test)
......
...@@ -7917,3 +7917,5 @@ ER_EMPTY_ROW_IN_TVC ...@@ -7917,3 +7917,5 @@ ER_EMPTY_ROW_IN_TVC
eng "Row with no elements is not allowed in table value constructor in this context" eng "Row with no elements is not allowed in table value constructor in this context"
ER_VERS_QUERY_IN_PARTITION ER_VERS_QUERY_IN_PARTITION
eng "SYSTEM_TIME partitions in table %`s does not support historical query" 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"
...@@ -618,7 +618,7 @@ static SQL_HANDLER *mysql_ha_find_handler(THD *thd, const LEX_CSTRING *name) ...@@ -618,7 +618,7 @@ static SQL_HANDLER *mysql_ha_find_handler(THD *thd, const LEX_CSTRING *name)
static bool static bool
mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
enum enum_ha_read_modes mode, const char *keyname, 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) Item *cond, bool in_prepare)
{ {
THD *thd= handler->thd; THD *thd= handler->thd;
...@@ -660,6 +660,18 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, ...@@ -660,6 +660,18 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
Item *item; Item *item;
key_part_map keypart_map; key_part_map keypart_map;
uint key_len; 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) if (key_expr->elements > keyinfo->user_defined_key_parts)
{ {
...@@ -667,6 +679,16 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler, ...@@ -667,6 +679,16 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
keyinfo->user_defined_key_parts); keyinfo->user_defined_key_parts);
return 1; 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++) for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)
{ {
my_bitmap_map *old_map; my_bitmap_map *old_map;
...@@ -841,7 +863,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -841,7 +863,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
goto err0; // mysql_lock_tables() printed error message already 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; goto err;
mode= handler->mode; mode= handler->mode;
keyno= handler->keyno; keyno= handler->keyno;
...@@ -1000,14 +1023,16 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -1000,14 +1023,16 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables, SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode, enum enum_ha_read_modes mode,
const char *keyname, 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; SQL_HANDLER *handler;
DBUG_ENTER("mysql_ha_read_prepare"); DBUG_ENTER("mysql_ha_read_prepare");
if (!(handler= mysql_ha_find_handler(thd, &tables->alias))) if (!(handler= mysql_ha_find_handler(thd, &tables->alias)))
DBUG_RETURN(0); DBUG_RETURN(0);
tables->table= handler->table; // This is used by fix_fields 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(0);
DBUG_RETURN(handler); DBUG_RETURN(handler);
} }
......
...@@ -80,5 +80,6 @@ void mysql_ha_rm_temporary_tables(THD *thd); ...@@ -80,5 +80,6 @@ void mysql_ha_rm_temporary_tables(THD *thd);
SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables, SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode, enum enum_ha_read_modes mode,
const char *keyname, const char *keyname,
List<Item> *key_expr, Item *cond); List<Item> *key_expr, enum ha_rkey_function ha_rkey_mode,
Item *cond);
#endif #endif
...@@ -2204,6 +2204,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, ...@@ -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, if (!(ha_table= mysql_ha_read_prepare(thd, tables, lex->ha_read_mode,
lex->ident.str, lex->ident.str,
lex->insert_list, lex->insert_list,
lex->ha_rkey_mode,
lex->select_lex.where))) lex->select_lex.where)))
DBUG_RETURN(1); DBUG_RETURN(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment