Bug#34587 Creating a view inside a stored procedure leads to a server crash

The problem is that when a stored procedure is being parsed for
the first execution, the body is copied to a temporary buffer
which is disregarded sometime after the statement is parsed.
And during this parsing phase, the rule for CREATE VIEW was
holding a reference to the string being parsed for use during
the execution of the CREATE VIEW statement, leading to invalid
memory access later.

The solution is to allocate and copy the SELECT of a CREATE
VIEW statement using the thread memory root, which is set to
the permanent arena of the stored procedure. 
parent 6bf1306b
...@@ -3720,6 +3720,16 @@ DROP VIEW v1; ...@@ -3720,6 +3720,16 @@ DROP VIEW v1;
# -- End of test case for Bug#32538. # -- End of test case for Bug#32538.
drop view if exists a;
drop procedure if exists p;
create procedure p()
begin
declare continue handler for sqlexception begin end;
create view a as select 1;
end|
call p();
call p();
drop procedure p;
# ----------------------------------------------------------------- # -----------------------------------------------------------------
# -- End of 5.1 tests. # -- End of 5.1 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
...@@ -3601,6 +3601,26 @@ DROP VIEW v1; ...@@ -3601,6 +3601,26 @@ DROP VIEW v1;
--echo # -- End of test case for Bug#32538. --echo # -- End of test case for Bug#32538.
--echo --echo
#
# Bug#34587 Creating a view inside a stored procedure leads to a server crash
#
--disable_warnings
drop view if exists a;
drop procedure if exists p;
--enable_warnings
delimiter |;
create procedure p()
begin
declare continue handler for sqlexception begin end;
create view a as select 1;
end|
delimiter ;|
call p();
call p();
drop procedure p;
########################################################################### ###########################################################################
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
......
...@@ -1513,10 +1513,8 @@ typedef struct st_lex : public Query_tables_list ...@@ -1513,10 +1513,8 @@ typedef struct st_lex : public Query_tables_list
/* store original leaf_tables for INSERT SELECT and PS/SP */ /* store original leaf_tables for INSERT SELECT and PS/SP */
TABLE_LIST *leaf_tables_insert; TABLE_LIST *leaf_tables_insert;
/** Start of SELECT of CREATE VIEW statement */ /** SELECT of CREATE VIEW statement */
const char* create_view_select_start; LEX_STRING create_view_select;
/** End of SELECT of CREATE VIEW statement */
const char* create_view_select_end;
/** Start of 'ON table', in trigger statements. */ /** Start of 'ON table', in trigger statements. */
const char* raw_trg_on_table_name_begin; const char* raw_trg_on_table_name_begin;
......
...@@ -237,7 +237,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, ...@@ -237,7 +237,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
/* This is ensured in the parser. */ /* This is ensured in the parser. */
DBUG_ASSERT(!lex->proc_list.first && !lex->result && DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
!lex->param_list.elements && !lex->derived_tables); !lex->param_list.elements);
if (mode != VIEW_CREATE_NEW) if (mode != VIEW_CREATE_NEW)
{ {
...@@ -718,11 +718,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ...@@ -718,11 +718,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
/* fill structure */ /* fill structure */
view->select_stmt.str= view_query.c_ptr_safe(); view->select_stmt.str= view_query.c_ptr_safe();
view->select_stmt.length= view_query.length(); view->select_stmt.length= view_query.length();
view->source= thd->lex->create_view_select;
view->source.str= (char*) thd->lex->create_view_select_start;
view->source.length= (thd->lex->create_view_select_end
- thd->lex->create_view_select_start);
trim_whitespace(thd->charset(), & view->source);
view->file_version= 1; view->file_version= 1;
view->calc_md5(md5); view->calc_md5(md5);
......
...@@ -12056,18 +12056,22 @@ view_select: ...@@ -12056,18 +12056,22 @@ view_select:
lex->parsing_options.allows_select_into= FALSE; lex->parsing_options.allows_select_into= FALSE;
lex->parsing_options.allows_select_procedure= FALSE; lex->parsing_options.allows_select_procedure= FALSE;
lex->parsing_options.allows_derived= FALSE; lex->parsing_options.allows_derived= FALSE;
lex->create_view_select_start= lip->get_cpp_ptr(); lex->create_view_select.str= (char *) lip->get_cpp_ptr();
} }
view_select_aux view_check_option view_select_aux view_check_option
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
LEX *lex= Lex; LEX *lex= Lex;
Lex_input_stream *lip= thd->m_lip; Lex_input_stream *lip= thd->m_lip;
uint len= lip->get_cpp_ptr() - lex->create_view_select.str;
void *create_view_select= thd->memdup(lex->create_view_select.str, len);
lex->create_view_select.length= len;
lex->create_view_select.str= (char *) create_view_select;
trim_whitespace(thd->charset(), &lex->create_view_select);
lex->parsing_options.allows_variable= TRUE; lex->parsing_options.allows_variable= TRUE;
lex->parsing_options.allows_select_into= TRUE; lex->parsing_options.allows_select_into= TRUE;
lex->parsing_options.allows_select_procedure= TRUE; lex->parsing_options.allows_select_procedure= TRUE;
lex->parsing_options.allows_derived= TRUE; lex->parsing_options.allows_derived= TRUE;
lex->create_view_select_end= lip->get_cpp_ptr();
} }
; ;
......
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