diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index 87b8166ef91..be0781af002 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -557,6 +557,18 @@ i call p(3); i 1 +# +# MDEV-15947 ASAN heap-use-after-free in Item_ident::print or in my_strcasecmp_utf8 or unexpected ER_BAD_FIELD_ERROR upon call of stored procedure reading from versioned table +# +create or replace table t1 (i int) with system versioning; +create or replace procedure p() select * from t1; +call p; +i +flush tables; +call p; +i +call p; +i drop procedure p; drop table t1; call verify_trt_dummy(34); diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index 845cf731af1..b7c2d500da1 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -363,6 +363,16 @@ call p(1); alter table t1 add system versioning; call p(2); call p(3); + +--echo # +--echo # MDEV-15947 ASAN heap-use-after-free in Item_ident::print or in my_strcasecmp_utf8 or unexpected ER_BAD_FIELD_ERROR upon call of stored procedure reading from versioned table +--echo # +create or replace table t1 (i int) with system versioning; +create or replace procedure p() select * from t1; +call p; +flush tables; +call p; +call p; drop procedure p; drop table t1; diff --git a/sql/sql_class.h b/sql/sql_class.h index 26876538828..7a854e0c217 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3669,6 +3669,10 @@ public: lex_str->length= length; return lex_str; } + LEX_CSTRING *make_clex_string(const LEX_CSTRING from) + { + return make_clex_string(from.str, from.length); + } // Allocate LEX_STRING for character set conversion bool alloc_lex_string(LEX_STRING *dst, size_t length) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fbd2f43ad25..317a7272793 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -822,8 +822,10 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway } - const LEX_CSTRING *fstart= &table->table->vers_start_field()->field_name; - const LEX_CSTRING *fend= &table->table->vers_end_field()->field_name; + const LEX_CSTRING *fstart= + thd->make_clex_string(table->table->vers_start_field()->field_name); + const LEX_CSTRING *fend= + thd->make_clex_string(table->table->vers_end_field()->field_name); Item *row_start= newx Item_field(thd, &this->context, table->db.str, table->alias.str, fstart);