summaryrefslogtreecommitdiff
path: root/sql/sp.cc
diff options
context:
space:
mode:
authorDavi Arnaut <Davi.Arnaut@Sun.COM>2009-11-21 09:18:21 -0200
committerDavi Arnaut <Davi.Arnaut@Sun.COM>2009-11-21 09:18:21 -0200
commit3fe5cd80ae064883edfdd189a99905d7036bb754 (patch)
treef0dceec63aed8b9e4a3a33ab0bab91594df0ff8d /sql/sp.cc
parent8e80deb52f64d345e64b146b9aea5a96b207621b (diff)
downloadmariadb-git-3fe5cd80ae064883edfdd189a99905d7036bb754.tar.gz
Bug#41726: upgrade from 5.0 to 5.1.30 crashes if you didn't run mysql_upgrade
The problem is that the server could crash when attempting to access a non-conformant proc system table. One such case was a crash when invoking stored procedure related statements on a 5.1 server with a proc system table in the 5.0 format. The solution is to validate the proc system table format before attempts to access it are made. If the table is not in the format that the server expects, a message is written to the error log and the statement that caused the table to be accessed fails.
Diffstat (limited to 'sql/sp.cc')
-rw-r--r--sql/sp.cc194
1 files changed, 181 insertions, 13 deletions
diff --git a/sql/sp.cc b/sql/sp.cc
index b254ba8e694..d3c5dfb96d0 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -70,6 +70,122 @@ enum
MYSQL_PROC_FIELD_COUNT
};
+static const
+TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] =
+{
+ {
+ { C_STRING_WITH_LEN("db") },
+ { C_STRING_WITH_LEN("char(64)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("name") },
+ { C_STRING_WITH_LEN("char(64)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("type") },
+ { C_STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("specific_name") },
+ { C_STRING_WITH_LEN("char(64)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("language") },
+ { C_STRING_WITH_LEN("enum('SQL')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("sql_data_access") },
+ { C_STRING_WITH_LEN("enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("is_deterministic") },
+ { C_STRING_WITH_LEN("enum('YES','NO')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("security_type") },
+ { C_STRING_WITH_LEN("enum('INVOKER','DEFINER')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("param_list") },
+ { C_STRING_WITH_LEN("blob") },
+ { NULL, 0 }
+ },
+
+ {
+ { C_STRING_WITH_LEN("returns") },
+ { C_STRING_WITH_LEN("longblob") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("body") },
+ { C_STRING_WITH_LEN("longblob") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("definer") },
+ { C_STRING_WITH_LEN("char(77)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("created") },
+ { C_STRING_WITH_LEN("timestamp") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("modified") },
+ { C_STRING_WITH_LEN("timestamp") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("sql_mode") },
+ { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
+ "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+ "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
+ "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
+ "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
+ "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
+ "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
+ "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") },
+ { NULL, 0 }
+ },
+ {
+ { C_STRING_WITH_LEN("comment") },
+ { C_STRING_WITH_LEN("char(64)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("character_set_client") },
+ { C_STRING_WITH_LEN("char(32)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("collation_connection") },
+ { C_STRING_WITH_LEN("char(32)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("db_collation") },
+ { C_STRING_WITH_LEN("char(32)") },
+ { C_STRING_WITH_LEN("utf8") }
+ },
+ {
+ { C_STRING_WITH_LEN("body_utf8") },
+ { C_STRING_WITH_LEN("longblob") },
+ { NULL, 0 }
+ }
+};
+
+static const TABLE_FIELD_DEF
+ proc_table_def= {MYSQL_PROC_FIELD_COUNT, proc_table_fields};
+
/*************************************************************************/
/**
@@ -247,6 +363,50 @@ Stored_routine_creation_ctx::load_from_db(THD *thd,
/*************************************************************************/
+class Proc_table_intact : public Table_check_intact
+{
+private:
+ bool m_print_once;
+
+public:
+ Proc_table_intact() : m_print_once(TRUE) {}
+
+protected:
+ void report_error(uint code, const char *fmt, ...);
+};
+
+
+/**
+ Report failure to validate the mysql.proc table definition.
+ Print a message to the error log only once.
+*/
+
+void Proc_table_intact::report_error(uint code, const char *fmt, ...)
+{
+ va_list args;
+ char buf[512];
+
+ va_start(args, fmt);
+ my_vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ if (code)
+ my_message(code, buf, MYF(0));
+ else
+ my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "proc");
+
+ if (m_print_once)
+ {
+ m_print_once= FALSE;
+ sql_print_error("%s", buf);
+ }
+};
+
+
+/** Single instance used to control printing to the error log. */
+static Proc_table_intact proc_table_intact;
+
+
/**
Open the mysql.proc table for read.
@@ -266,15 +426,17 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup)
DBUG_ENTER("open_proc_table_for_read");
TABLE_LIST table;
- bzero((char*) &table, sizeof(table));
- table.db= (char*) "mysql";
- table.table_name= table.alias= (char*)"proc";
- table.lock_type= TL_READ;
+ table.init_one_table("mysql", "proc", TL_READ);
+
+ if (open_system_tables_for_read(thd, &table, backup))
+ DBUG_RETURN(NULL);
- if (!open_system_tables_for_read(thd, &table, backup))
+ if (!proc_table_intact.check(table.table, &proc_table_def))
DBUG_RETURN(table.table);
- else
- DBUG_RETURN(0);
+
+ close_system_tables(thd, backup);
+
+ DBUG_RETURN(NULL);
}
@@ -296,13 +458,19 @@ static TABLE *open_proc_table_for_update(THD *thd)
{
DBUG_ENTER("open_proc_table_for_update");
- TABLE_LIST table;
- bzero((char*) &table, sizeof(table));
- table.db= (char*) "mysql";
- table.table_name= table.alias= (char*)"proc";
- table.lock_type= TL_WRITE;
+ TABLE *table;
+ TABLE_LIST table_list;
+ table_list.init_one_table("mysql", "proc", TL_WRITE);
+
+ if (!(table= open_system_table_for_update(thd, &table_list)))
+ DBUG_RETURN(NULL);
+
+ if (!proc_table_intact.check(table, &proc_table_def))
+ DBUG_RETURN(table);
+
+ close_thread_tables(thd);
- DBUG_RETURN(open_system_table_for_update(thd, &table));
+ DBUG_RETURN(NULL);
}