Commit eb5bf2ec authored by pem@mysql.com's avatar pem@mysql.com

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).
parent 1111b5cd
...@@ -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)"
...@@ -1420,8 +1420,8 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src) ...@@ -1420,8 +1420,8 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src)
Instead this fact will be discovered during query execution. Instead this fact will be discovered during query execution.
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) */
my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), ret); if (ret == SP_PARSE_ERROR)
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);
} }
...@@ -1518,8 +1529,8 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ...@@ -1518,8 +1529,8 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
tabs_changed - Set to TRUE some tables were added, FALSE otherwise tabs_changed - Set to TRUE some tables were added, FALSE otherwise
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
int int
...@@ -1544,8 +1555,8 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock, ...@@ -1544,8 +1555,8 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock,
aux_lex - LEX representing view aux_lex - LEX representing view
RETURN VALUE RETURN VALUE
0 - success 0 - success
-x - failure (error code, like SP_PARSE_ERROR et al) non-0 - failure
*/ */
int int
...@@ -1572,8 +1583,8 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) ...@@ -1572,8 +1583,8 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
triggers - triggers of the table triggers - triggers of the table
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