diff --git a/client/mysqltest.c b/client/mysqltest.c index 8e72bc8edb867e1bb4af4e4d5f01a086b3d7e474..ca4d931970704053d4bbc1490aebb079778967d4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -66,7 +66,8 @@ #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif -#define MAX_QUERY 131072 +/* MAX_QUERY is 256K -- there is a test in sp-big that is >128K */ +#define MAX_QUERY (256*1024) #define MAX_VAR_NAME 256 #define MAX_COLUMNS 256 #define PAD_SIZE 128 diff --git a/mysql-test/r/sp-big.result b/mysql-test/r/sp-big.result new file mode 100644 index 0000000000000000000000000000000000000000..004ff586aabb11af91e84c4ee83d30940a91baff --- /dev/null +++ b/mysql-test/r/sp-big.result @@ -0,0 +1,15 @@ +drop procedure if exists test.longprocedure; +drop table if exists t1; +create table t1 (a int); +insert into t1 values (1),(2),(3); +length +107520 +select length(routine_definition) from information_schema.routines where routine_schema = 'test' and routine_name = 'longprocedure'; +length(routine_definition) +107530 +call test.longprocedure(@value); +select @value; +@value +3 +drop procedure test.longprocedure; +drop table t1; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 277115733d46011bd0ce567dc34ee352631cc430..d2872878cb9d2c5adcf56a33fca630dec8c1446f 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -172,7 +172,7 @@ proc CREATE TABLE `proc` ( `security_type` enum('INVOKER','DEFINER') NOT NULL default 'DEFINER', `param_list` blob NOT NULL, `returns` char(64) NOT NULL default '', - `body` blob NOT NULL, + `body` longblob NOT NULL, `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '', `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `modified` timestamp NOT NULL default '0000-00-00 00:00:00', diff --git a/mysql-test/t/sp-big.test b/mysql-test/t/sp-big.test new file mode 100644 index 0000000000000000000000000000000000000000..769d77dbef9e07476e00e4bb7e9b6014af2c829a --- /dev/null +++ b/mysql-test/t/sp-big.test @@ -0,0 +1,33 @@ +# +# Bug #11602: SP with very large body not handled well +# + +--disable_warnings +drop procedure if exists test.longprocedure; +drop table if exists t1; +--enable_warnings + +create table t1 (a int); +insert into t1 values (1),(2),(3); + +let $body=`select repeat('select count(*) into out1 from t1;\n', 3072)`; + +delimiter //; +--disable_query_log +eval select length('$body') as length// +eval create procedure test.longprocedure (out out1 int) deterministic +begin + $body +end// +--enable_query_log + +delimiter ;// + +# this is larger than the length above, because it includes the 'begin' and +# 'end' bits and some whitespace +select length(routine_definition) from information_schema.routines where routine_schema = 'test' and routine_name = 'longprocedure'; + +call test.longprocedure(@value); select @value; + +drop procedure test.longprocedure; +drop table t1; diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index a3036b5c10ba5369bd4d31da14dee8f057910e4b..383f8b80dc8032e52d1405170f578eacb5f1d95c 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -683,7 +683,7 @@ then c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL," c_p="$c_p param_list blob DEFAULT '' NOT NULL," c_p="$c_p returns char(64) DEFAULT '' NOT NULL," - c_p="$c_p body blob DEFAULT '' NOT NULL," + c_p="$c_p body longblob DEFAULT '' NOT NULL," c_p="$c_p definer char(77) collate utf8_bin DEFAULT '' NOT NULL," c_p="$c_p created timestamp," c_p="$c_p modified timestamp," diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index b93e0a47b1bec6c7078838ca542a5a827abf69e0..f67bab4451421f627eac7c9a9369fe80a44dc86f 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -426,7 +426,7 @@ CREATE TABLE IF NOT EXISTS proc ( security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, - body blob DEFAULT '' NOT NULL, + body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, @@ -477,6 +477,7 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, + MODIFY body longblob DEFAULT '' NOT NULL, MODIFY sql_mode set('REAL_AS_FLOAT', 'PIPES_AS_CONCAT', diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 459560ccac8bd8df209d9bbc369c9e3863d85222..5dd5cd9c775f03226d69959ecae8bc005812054f 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5386,3 +5386,5 @@ ER_TRG_IN_WRONG_SCHEMA eng "Trigger in wrong schema" ER_STACK_OVERRUN_NEED_MORE eng "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack." +ER_TOO_LONG_BODY 42000 S1009 + eng "Routine body for '%-.100s' is too long" diff --git a/sql/sp.cc b/sql/sp.cc index dec0eee00953439cfa104bd12f17c06bc3c80b16..dfe3493528f7f472f62f615af5b583f53a554c47 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -503,6 +503,11 @@ db_create_routine(THD *thd, int type, sp_head *sp) ret= SP_BAD_IDENTIFIER; goto done; } + if (sp->m_body.length > table->field[MYSQL_PROC_FIELD_BODY]->field_length) + { + ret= SP_BODY_TOO_LONG; + goto done; + } table->field[MYSQL_PROC_FIELD_DB]-> store(sp->m_db.str, sp->m_db.length, system_charset_info); table->field[MYSQL_PROC_FIELD_NAME]-> diff --git a/sql/sp.h b/sql/sp.h index b8af8d3a32148fd9946c42c562168364ee988a0f..86351f61de9213e78aa1ff65c2e5b30b89402ddb 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -29,6 +29,7 @@ #define SP_INTERNAL_ERROR -7 #define SP_NO_DB_ERROR -8 #define SP_BAD_IDENTIFIER -9 +#define SP_BODY_TOO_LONG -10 /* Drop all routines in database 'db' */ int diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f1950d36b230c7e9989a3c3cf1037c86526c02a9..bf33f841eb82937caee682f20bce8c400471049e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4107,6 +4107,12 @@ mysql_execute_command(THD *thd) delete lex->sphead; lex->sphead= 0; goto error; + case SP_BODY_TOO_LONG: + my_error(ER_TOO_LONG_BODY, MYF(0), name); + lex->unit.cleanup(); + delete lex->sphead; + lex->sphead= 0; + goto error; default: my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); lex->unit.cleanup();