revision-id: cc0bc69f2d28aace12487f930677abcdffa5ce97 (mariadb-10.3.6-102-gcc0bc69) parent(s): 73a10cbcc5178ae5378abb821428d35d3276b4da committer: Alexey Botchkov timestamp: 2018-05-06 02:37:20 +0400 message: MDEV-15813 ASAN use-after-poison in hp_hashnr upon HANDLER READ on a versioned HEAP table. hp_rkey now returns an error if we try to use HASH key where it doesn't work. --- include/my_base.h | 3 ++- include/my_handler_errors.h | 3 ++- mysql-test/suite/heap/heap_hash.result | 19 +++++++++++++++++++ mysql-test/suite/heap/heap_hash.test | 18 ++++++++++++++++++ sql/handler.cc | 5 +++++ sql/share/errmsg-utf8.txt | 2 ++ sql/sql_handler.cc | 4 +++- storage/heap/hp_rkey.c | 8 ++++++++ 8 files changed, 59 insertions(+), 3 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index c36072c..8d04b68 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -522,7 +522,8 @@ enum ha_base_keytype { #define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */ #define HA_ERR_SEQUENCE_INVALID_DATA 195 #define HA_ERR_SEQUENCE_RUN_OUT 196 -#define HA_ERR_LAST 196 /* Copy of last error nr * */ +#define HA_ERR_KEY_DOESNT_SUPPORT 197 /* Index doesn't support the operation. */ +#define HA_ERR_LAST 197 /* Copy of last error nr * */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_handler_errors.h b/include/my_handler_errors.h index f682861..9cdbfac 100644 --- a/include/my_handler_errors.h +++ b/include/my_handler_errors.h @@ -107,7 +107,8 @@ static const char *handler_error_messages[]= "Foreign key cascade delete/update exceeds max depth", "Tablespace is missing for a table", "Sequence has been run out", - "Sequence values are conflicting" + "Sequence values are conflicting", + "HASH key doesn't support that operation" }; #endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/mysql-test/suite/heap/heap_hash.result b/mysql-test/suite/heap/heap_hash.result index 55d4358..cba39c1 100644 --- a/mysql-test/suite/heap/heap_hash.result +++ b/mysql-test/suite/heap/heap_hash.result @@ -467,3 +467,22 @@ c1 bar2 DROP TABLE t1; End of 5.5 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/heap/heap_hash.test b/mysql-test/suite/heap/heap_hash.test index 3fe95e1..5a08c6d 100644 --- a/mysql-test/suite/heap/heap_hash.test +++ b/mysql-test/suite/heap/heap_hash.test @@ -347,3 +347,21 @@ SELECT * FROM t1 WHERE c1='bar2'; DROP TABLE t1; --echo End of 5.5 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/sql/handler.cc b/sql/handler.cc index ef1d599..7560f55 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3793,6 +3793,11 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TABLE_IN_FK_CHECK: textno= ER_TABLE_IN_FK_CHECK; break; + case HA_ERR_KEY_DOESNT_SUPPORT: + textno= ER_KEY_DOESNT_SUPPORT; + my_error(ER_KEY_DOESNT_SUPPORT, errflag, + table_share->key_info[table->file->active_index].name); + DBUG_VOID_RETURN; default: { /* The error was "unknown" to this function. diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index c55ac4f..fcd20d8 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7915,3 +7915,5 @@ ER_UPDATED_COLUMN_ONLY_ONCE eng "The column %`s.%`s cannot be changed more than once in a single UPDATE statement" ER_EMPTY_ROW_IN_TVC eng "Row with no elements is not allowed in table value constructor in this context" +ER_KEY_DOESNT_SUPPORT + eng "HASH index %`s does not support this operation" diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index ddc9c4a..dba7134 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -947,7 +947,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { /* Don't give error in the log file for some expected problems */ - if (error != HA_ERR_RECORD_CHANGED && error != HA_ERR_WRONG_COMMAND) + if (error != HA_ERR_RECORD_CHANGED && + error != HA_ERR_WRONG_COMMAND && + error != HA_ERR_KEY_DOESNT_SUPPORT) sql_print_error("mysql_ha_read: Got error %d when reading " "table '%s'", error, tables->table_name.str); diff --git a/storage/heap/hp_rkey.c b/storage/heap/hp_rkey.c index 692e1a0..a7b81ae 100644 --- a/storage/heap/hp_rkey.c +++ b/storage/heap/hp_rkey.c @@ -60,6 +60,14 @@ int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key, } else { + /* + HASH key doesn't support search other than equality, + and doesn't support prefix search. + */ + if (find_flag != HA_READ_KEY_EXACT || + (1UL << share->keydef[inx].keysegs) != keypart_map + 1) + DBUG_RETURN(my_errno= HA_ERR_KEY_DOESNT_SUPPORT); + if (!(pos= hp_search(info, share->keydef + inx, key, 0))) { info->update= HA_STATE_NO_KEY;