Commit d4088df5 authored by unknown's avatar unknown

Fixed BUG#14233: Crash after tampering with the mysql.proc table

  Post-review version. Some minor review fixes, but also changed the way
  some errors are handled: Don't return specific parse errors; instead
  always use the more general "table corrupt" error (amended accordingly).


mysql-test/r/sp-destruct.result:
  Updated results.
mysql-test/r/sp-error.result:
  Updated for fully qualified name in "no return" error message.
mysql-test/t/sp-destruct.test:
  Adopted the more consistent error handling for a corrupted mysql.proc table.
  (No more "parse error" et al).
sql/share/errmsg.txt:
  Changed ER_SP_PROC_TABLE_CORRUPT to be more explicit.
sql/sp.cc:
  Review fixes.
  Changed the handling of parse errors, and added the routine name to the "table corrupt" error message.
sql/sql_base.cc:
  Review changes: Change error tests and added comments.
sql/sql_parse.cc:
  Mored ER_SP_NORETURN test of functions to sql_yacc.yy for more general error handling.
sql/sql_yacc.yy:
  Mored ER_SP_NORETURN test of functions from sql_parse.cc for more general error handling.
parent df226305
...@@ -11,11 +11,11 @@ create table t1 (id int); ...@@ -11,11 +11,11 @@ create table t1 (id int);
create trigger t1_ai after insert on t1 for each row call bug14233(); create trigger t1_ai after insert on t1 for each row call bug14233();
alter table mysql.proc drop type; alter table mysql.proc drop type;
call bug14233(); call bug14233();
ERROR HY000: The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
create view v1 as select bug14233_f(); create view v1 as select bug14233_f();
ERROR HY000: The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) ERROR HY000: Failed to load routine test.bug14233_f. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
insert into t1 values (0); insert into t1 values (0);
ERROR HY000: The table mysql.proc is missing, corrupt, or contains bad data (internal code -5) ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
flush table mysql.proc; flush table mysql.proc;
call bug14233(); call bug14233();
ERROR HY000: Incorrect information in file: './mysql/proc.frm' ERROR HY000: Incorrect information in file: './mysql/proc.frm'
...@@ -59,21 +59,19 @@ values ...@@ -59,21 +59,19 @@ values
'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' 'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
); );
select bug14233_1(); select bug14233_1();
ERROR 0A000: Not allowed to return a result set from a function ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
create view v1 as select bug14233_1(); create view v1 as select bug14233_1();
ERROR 0A000: Not allowed to return a result set from a function ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
select bug14233_2(); select bug14233_2();
ERROR 2F005: FUNCTION bug14233_2 ended without RETURN ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
create view v1 as select bug14233_2(); create view v1 as select bug14233_2();
select * from v1; ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
ERROR 2F005: FUNCTION bug14233_2 ended without RETURN
call bug14233_3(); call bug14233_3();
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'wpsj sa ^#!@ ' at line 3 ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
drop trigger t1_ai; drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3(); create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0); insert into t1 values (0);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'wpsj sa ^#!@ ' at line 3 ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
delete from mysql.proc where name like 'bug14233%'; delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai; drop trigger t1_ai;
drop table t1; drop table t1;
drop view v1;
...@@ -124,7 +124,7 @@ begin ...@@ -124,7 +124,7 @@ begin
declare x int; declare x int;
set x = val+3; set x = val+3;
end| end|
ERROR 42000: No RETURN found in FUNCTION f ERROR 42000: No RETURN found in FUNCTION test.f
create function f(val int) returns int create function f(val int) returns int
begin begin
declare x int; declare x int;
......
...@@ -101,26 +101,24 @@ values ...@@ -101,26 +101,24 @@ values
'root@localhost', NOW() , '0000-00-00 00:00:00', '', '' 'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
); );
--error ER_SP_NO_RETSET --error ER_SP_PROC_TABLE_CORRUPT
select bug14233_1(); select bug14233_1();
--error ER_SP_NO_RETSET --error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_1(); create view v1 as select bug14233_1();
--error ER_SP_NORETURNEND --error ER_SP_PROC_TABLE_CORRUPT
select bug14233_2(); select bug14233_2();
--error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_2(); create view v1 as select bug14233_2();
--error ER_SP_NORETURNEND
select * from v1;
--error ER_PARSE_ERROR --error ER_SP_PROC_TABLE_CORRUPT
call bug14233_3(); call bug14233_3();
drop trigger t1_ai; drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3(); create trigger t1_ai after insert on t1 for each row call bug14233_3();
--error ER_PARSE_ERROR --error ER_SP_PROC_TABLE_CORRUPT
insert into t1 values (0); insert into t1 values (0);
# Clean-up # Clean-up
delete from mysql.proc where name like 'bug14233%'; delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai; drop trigger t1_ai;
drop table t1; drop table t1;
drop view v1;
...@@ -5422,4 +5422,4 @@ ER_NO_REFERENCED_ROW_2 23000 ...@@ -5422,4 +5422,4 @@ ER_NO_REFERENCED_ROW_2 23000
ER_SP_BAD_VAR_SHADOW 42000 ER_SP_BAD_VAR_SHADOW 42000
eng "Variable '%-.64s' must be quoted with `...`, or renamed" eng "Variable '%-.64s' must be quoted with `...`, or renamed"
ER_SP_PROC_TABLE_CORRUPT ER_SP_PROC_TABLE_CORRUPT
eng "The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
...@@ -1421,7 +1421,7 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src) ...@@ -1421,7 +1421,7 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src)
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
static int static int
...@@ -1430,7 +1430,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1430,7 +1430,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
bool first_no_prelock, bool *tabs_changed) bool first_no_prelock, bool *tabs_changed)
{ {
int ret= 0; int ret= 0;
bool result= FALSE; int tabschnd= 0; /* Set if tables changed */
bool first= TRUE; bool first= TRUE;
DBUG_ENTER("sp_cache_routines_and_add_tables_aux"); DBUG_ENTER("sp_cache_routines_and_add_tables_aux");
...@@ -1478,11 +1478,21 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1478,11 +1478,21 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
/* Fall through */ /* Fall through */
default: default:
/* /*
In some cases no error has been set (e.g. get field failed, Any error when loading an existing routine is either some problem
when the proc table has been tampered with). with the mysql.proc table, or a parse error because the contents
has been tampered with (in which case we clear that error).
*/ */
if (! thd->net.report_error) if (ret == SP_PARSE_ERROR)
my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), ret); thd->clear_error();
if (!thd->net.report_error)
{
char n[NAME_LEN*2+2];
/* m_qname.str is not always \0 terminated */
memcpy(n, name.m_qname.str, name.m_qname.length);
n[name.m_qname.length]= '\0';
my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret);
}
break; break;
} }
delete newlex; delete newlex;
...@@ -1493,13 +1503,14 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1493,13 +1503,14 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
if (!(first && first_no_prelock)) if (!(first && first_no_prelock))
{ {
sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines); sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines);
result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); tabschnd|=
sp->add_used_tables_to_table_list(thd, &lex->query_tables_last);
} }
} }
first= FALSE; first= FALSE;
} }
if (tabs_changed) if (tabs_changed) /* it can be NULL */
*tabs_changed= result; *tabs_changed= tabschnd;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -1519,7 +1530,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1519,7 +1530,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
int int
...@@ -1545,7 +1556,7 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock, ...@@ -1545,7 +1556,7 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock,
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
int int
...@@ -1573,7 +1584,7 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) ...@@ -1573,7 +1584,7 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
int int
......
...@@ -1986,9 +1986,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) ...@@ -1986,9 +1986,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
if (sp_cache_routines_and_add_tables(thd, thd->lex, if (sp_cache_routines_and_add_tables(thd, thd->lex,
first_no_prelocking, first_no_prelocking,
&tabs_changed) < 0) &tabs_changed))
{ {
result= -1; // Fatal error /*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err; goto err;
} }
else if ((tabs_changed || *start) && need_prelocking) else if ((tabs_changed || *start) && need_prelocking)
...@@ -2117,9 +2122,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) ...@@ -2117,9 +2122,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
if (!query_tables_last_own) if (!query_tables_last_own)
query_tables_last_own= thd->lex->query_tables_last; query_tables_last_own= thd->lex->query_tables_last;
if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex,
tables->table->triggers) < 0) tables->table->triggers))
{ {
result= -1; // Fatal error /*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err; goto err;
} }
} }
...@@ -2143,9 +2153,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) ...@@ -2143,9 +2153,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
if (!query_tables_last_own) if (!query_tables_last_own)
query_tables_last_own= thd->lex->query_tables_last; query_tables_last_own= thd->lex->query_tables_last;
if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex, if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex,
tables->view) < 0) tables->view))
{ {
result= -1; // Fatal error /*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err; goto err;
} }
} }
......
...@@ -4111,14 +4111,6 @@ mysql_execute_command(THD *thd) ...@@ -4111,14 +4111,6 @@ mysql_execute_command(THD *thd)
} }
} }
#endif #endif
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!(lex->sphead->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
}
/* /*
We need to copy name and db in order to use them for We need to copy name and db in order to use them for
......
...@@ -1475,6 +1475,11 @@ create_function_tail: ...@@ -1475,6 +1475,11 @@ create_function_tail:
YYABORT; YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION; lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex, lex->spname); sp->init_strings(YYTHD, lex, lex->spname);
if (!(sp->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
YYABORT;
}
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (sp->m_old_cmq) if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
......
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