diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2019-05-14 14:01:15 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2019-07-30 10:39:12 +0200 |
commit | 999cce215fbee4d0bcdb8df920f460cfee46e41b (patch) | |
tree | d68a8ed4e1196362ff7662bd1cd2e4cf4b220084 /sql/sql_table.cc | |
parent | d6886b95d0d48d80deffa7f2190b8abd5ee8236b (diff) | |
download | mariadb-git-bb-10.2-MDEV-16932.tar.gz |
MDEV-16932: ASAN heap-use-after-free in my_charlen_utf8 / my_well_formed_char_length_utf8 on 2nd execution of SP with ALTER trying to add bad CHECKbb-10.2-MDEV-16932
Make automatic name generation during execution (not prepare).
Check result of memory allocation operation.
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index fbd6622b1b2..f395cac2f43 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -64,7 +64,7 @@ const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(THD *thd, const char *field_name, KEY *start, KEY *end); -static void make_unique_constraint_name(THD *thd, LEX_STRING *name, +static bool make_unique_constraint_name(THD *thd, LEX_STRING *name, List<Virtual_column_info> *vcol, uint *nr); static int copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, @@ -78,6 +78,8 @@ static bool prepare_blob_field(THD *thd, Column_definition *sql_field); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, uint *, handler *, KEY **, uint *, int); static uint blob_length_by_type(enum_field_types type); +static bool fix_constraints_names(THD *thd, List<Virtual_column_info> + *check_constraint_list); /** @brief Helper function for explain_filename @@ -4183,15 +4185,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, /* Check table level constraints */ create_info->check_constraint_list= &alter_info->check_constraint_list; { - uint nr= 1; List_iterator_fast<Virtual_column_info> c_it(alter_info->check_constraint_list); Virtual_column_info *check; while ((check= c_it++)) { - if (!check->name.length) - make_unique_constraint_name(thd, &check->name, - &alter_info->check_constraint_list, - &nr); + if (!check->name.length || check->automatic_name) + continue; + { /* Check that there's no repeating constraint names. */ List_iterator_fast<Virtual_column_info> @@ -4727,6 +4727,9 @@ int create_table_impl(THD *thd, DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d path: %s", db, table_name, internal_tmp_table, path)); + if (fix_constraints_names(thd, &alter_info->check_constraint_list)) + DBUG_RETURN(1); + if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) { if (create_info->data_file_name) @@ -5190,7 +5193,7 @@ make_unique_key_name(THD *thd, const char *field_name,KEY *start,KEY *end) Make an unique name for constraints without a name */ -static void make_unique_constraint_name(THD *thd, LEX_STRING *name, +static bool make_unique_constraint_name(THD *thd, LEX_STRING *name, List<Virtual_column_info> *vcol, uint *nr) { @@ -5213,9 +5216,10 @@ static void make_unique_constraint_name(THD *thd, LEX_STRING *name, { name->length= (size_t) (real_end - buff); name->str= thd->strmake(buff, name->length); - return; + return (name->str == NULL); } } + return FALSE; } @@ -5798,10 +5802,11 @@ static bool is_candidate_key(KEY *key) from the list if existing found. RETURN VALUES - NONE + TRUE error + FALSE OK */ -static void +static bool handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) { Field **f_ptr; @@ -6204,6 +6209,7 @@ remove_key: Virtual_column_info *check; TABLE_SHARE *share= table->s; uint c; + while ((check=it++)) { if (!(check->flags & Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS) && @@ -6231,10 +6237,44 @@ remove_key: } } - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } +static bool fix_constraints_names(THD *thd, List<Virtual_column_info> + *check_constraint_list) +{ + List_iterator<Virtual_column_info> it((*check_constraint_list)); + Virtual_column_info *check; + uint nr= 1; + DBUG_ENTER("fix_constraints_names"); + if (!check_constraint_list) + DBUG_RETURN(FALSE); + // Prevent accessing freed memory during generating unique names + while ((check=it++)) + { + if (check->automatic_name) + { + check->name.str= NULL; + check->name.length= 0; + } + } + it.rewind(); + // Generate unique names if needed + while ((check=it++)) + { + if (!check->name.length) + { + check->automatic_name= TRUE; + if (make_unique_constraint_name(thd, &check->name, + check_constraint_list, + &nr)) + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + /** Get Create_field object for newly created table by field index. @@ -9081,7 +9121,10 @@ do_continue:; } } - handle_if_exists_options(thd, table, alter_info); + if (handle_if_exists_options(thd, table, alter_info) || + fix_constraints_names(thd, &alter_info->check_constraint_list)) + DBUG_RETURN(true); + /* Look if we have to do anything at all. |