1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-25091 CREATE TABLE: field references qualified by a wrong table name succeed

Before FRM is written walk vcol expressions through
check_table_name_processor() and check if field items match (db,
table_name) qualifier.

We cannot do this in check_vcol_func_processor() as there is already
no table name qualifiers in expressions of written and loaded FRM.
This commit is contained in:
Aleksey Midenkov
2021-03-26 11:44:54 +03:00
parent 4649ba7493
commit 42f8548ff6
5 changed files with 188 additions and 5 deletions

View File

@ -76,7 +76,9 @@ static int copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
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);
uint *, handler *, KEY **, uint *, int,
const LEX_CSTRING db,
const LEX_CSTRING table_name);
static uint blob_length_by_type(enum_field_types type);
static bool fix_constraints_names(THD *thd, List<Virtual_column_info>
*check_constraint_list);
@ -1809,10 +1811,12 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
if (flags & WFRM_WRITE_SHADOW)
{
LEX_CSTRING db= { lpt->db, strlen(lpt->db) };
LEX_CSTRING table_name= { lpt->table_name, strlen(lpt->table_name) };
if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info,
&lpt->db_options, lpt->table->file,
&lpt->key_info_buffer, &lpt->key_count,
C_ALTER_TABLE))
C_ALTER_TABLE, db, table_name))
{
DBUG_RETURN(TRUE);
}
@ -3231,7 +3235,8 @@ static int
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Alter_info *alter_info, uint *db_options,
handler *file, KEY **key_info_buffer,
uint *key_count, int create_table_mode)
uint *key_count, int create_table_mode,
const LEX_CSTRING db, const LEX_CSTRING table_name)
{
const char *key_name;
Create_field *sql_field,*dup_field;
@ -3246,6 +3251,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
uint total_uneven_bit_length= 0;
int select_field_count= C_CREATE_SELECT(create_table_mode);
bool tmp_table= create_table_mode == C_ALTER_TABLE;
const bool create_simple= thd->lex->create_simple();
DBUG_ENTER("mysql_prepare_create_table");
LEX_STRING* connect_string = &create_info->connect_string;
@ -4138,6 +4144,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
create_info->null_bits= null_fields;
/* Check fields. */
Item::Check_table_name_prm walk_prm(db, table_name);
it.rewind();
while ((sql_field=it++))
{
@ -4182,6 +4189,37 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
DBUG_RETURN(TRUE);
}
if (create_simple)
{
/*
NOTE: we cannot do this in check_vcol_func_processor() as there is already
no table name qualifier in expression.
*/
if (sql_field->vcol_info &&
sql_field->vcol_info->expr->walk(&Item::check_table_name_processor,
false, (void *) &walk_prm))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS");
DBUG_RETURN(TRUE);
}
if (sql_field->default_value &&
sql_field->default_value->expr->walk(&Item::check_table_name_processor,
false, (void *) &walk_prm))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT");
DBUG_RETURN(TRUE);
}
if (sql_field->check_constraint &&
sql_field->check_constraint->expr->walk(&Item::check_table_name_processor,
false, (void *) &walk_prm))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK");
DBUG_RETURN(TRUE);
}
}
}
/* Check table level constraints */
@ -4191,6 +4229,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Virtual_column_info *check;
while ((check= c_it++))
{
if (create_simple && check->expr->walk(&Item::check_table_name_processor, false,
(void *) &walk_prm))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK");
DBUG_RETURN(TRUE);
}
if (!check->name.length || check->automatic_name)
continue;
@ -4477,6 +4521,8 @@ handler *mysql_create_frm_image(THD *thd,
{
uint db_options;
handler *file;
const LEX_CSTRING new_db= { db, strlen(db) };
const LEX_CSTRING new_table_name= { table_name, strlen(table_name) };
DBUG_ENTER("mysql_create_frm_image");
if (!alter_info->create_list.elements)
@ -4700,7 +4746,7 @@ handler *mysql_create_frm_image(THD *thd,
if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options,
file, key_info, key_count,
create_table_mode))
create_table_mode, new_db, new_table_name))
goto err;
create_info->table_options=db_options;
@ -7024,13 +7070,15 @@ bool mysql_compare_tables(TABLE *table,
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
KEY *key_info_buffer= NULL;
LEX_CSTRING db= { table->s->db.str, table->s->db.length };
LEX_CSTRING table_name= { table->s->db.str, table->s->table_name.length };
/* Create the prepared information. */
int create_table_mode= table->s->tmp_table == NO_TMP_TABLE ?
C_ORDINARY_CREATE : C_ALTER_TABLE;
if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info,
&db_options, table->file, &key_info_buffer,
&key_count, create_table_mode))
&key_count, create_table_mode, db, table_name))
DBUG_RETURN(1);
/* Some very basic checks. */