Commit 4fd6dd2d authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-29748 ASAN errors or server crash in File_parser::parse upon concurrent view operations

Read the version of the view share when we read definition to prevent
simultaniouse access to a view table SHARE (and so its MEM_ROOT)
from different threads.
parent e00ea301
...@@ -1175,19 +1175,26 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ...@@ -1175,19 +1175,26 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
bool mariadb_view_version_get(TABLE_SHARE *share) bool mariadb_view_version_get(TABLE_SHARE *share)
{ {
DBUG_ASSERT(share->is_view); DBUG_ASSERT(share->is_view);
DBUG_ASSERT(share->tabledef_version.length == 0);
if (!(share->tabledef_version.str= if (!(share->tabledef_version.str=
(uchar*) alloc_root(&share->mem_root, (uchar*) alloc_root(&share->mem_root,
MICROSECOND_TIMESTAMP_BUFFER_SIZE))) MICROSECOND_TIMESTAMP_BUFFER_SIZE)))
return TRUE; return TRUE;
share->tabledef_version.length= 0; // safety if the drfinition file is brocken
DBUG_ASSERT(share->view_def != NULL); DBUG_ASSERT(share->view_def != NULL);
if (share->view_def->parse((uchar *) &share->tabledef_version, NULL, if (share->view_def->parse((uchar *) &share->tabledef_version, NULL,
view_timestamp_parameters, 1, view_timestamp_parameters, 1,
&file_parser_dummy_hook)) &file_parser_dummy_hook))
{
// safety if the definition file is brocken
share->tabledef_version.length= 0;
my_error(ER_TABLE_CORRUPT, MYF(0),
share->db.str, share->table_name.str);
return TRUE; return TRUE;
}
DBUG_ASSERT(share->tabledef_version.length == MICROSECOND_TIMESTAMP_BUFFER_SIZE-1); DBUG_ASSERT(share->tabledef_version.length == MICROSECOND_TIMESTAMP_BUFFER_SIZE-1);
return FALSE; return FALSE;
} }
...@@ -1251,10 +1258,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, ...@@ -1251,10 +1258,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
mysql_derived_reinit(thd, NULL, table); mysql_derived_reinit(thd, NULL, table);
DEBUG_SYNC(thd, "after_cached_view_opened"); DEBUG_SYNC(thd, "after_cached_view_opened");
if (!share->tabledef_version.length) DBUG_ASSERT(share->tabledef_version.length);
{
mariadb_view_version_get(share);
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1308,15 +1312,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, ...@@ -1308,15 +1312,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
required_view_parameters, required_view_parameters,
&file_parser_dummy_hook))) &file_parser_dummy_hook)))
goto end; goto end;
if (!share->tabledef_version.length) DBUG_ASSERT(share->tabledef_version.length);
{
share->tabledef_version.str= (const uchar *)
memdup_root(&share->mem_root,
(const void *)
table->hr_timestamp.str,
(share->tabledef_version.length=
table->hr_timestamp.length));
}
if (!table->tabledef_version.length) if (!table->tabledef_version.length)
{ {
table->set_view_def_version(&table->hr_timestamp); table->set_view_def_version(&table->hr_timestamp);
......
...@@ -64,4 +64,6 @@ extern const LEX_CSTRING view_type; ...@@ -64,4 +64,6 @@ extern const LEX_CSTRING view_type;
void make_valid_column_names(List<Item> &item_list); void make_valid_column_names(List<Item> &item_list);
bool mariadb_view_version_get(TABLE_SHARE *share);
#endif /* SQL_VIEW_INCLUDED */ #endif /* SQL_VIEW_INCLUDED */
...@@ -633,7 +633,11 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) ...@@ -633,7 +633,11 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
if (!share->view_def) if (!share->view_def)
share->error= OPEN_FRM_ERROR_ALREADY_ISSUED; share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
else else
{
share->error= OPEN_FRM_OK; share->error= OPEN_FRM_OK;
if (mariadb_view_version_get(share))
share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
}
} }
else else
share->error= OPEN_FRM_NOT_A_TABLE; share->error= OPEN_FRM_NOT_A_TABLE;
......
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