diff options
-rw-r--r-- | mysql-test/r/sp-error.result | 28 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 38 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 2 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 24 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 6 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 12 |
6 files changed, 105 insertions, 5 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 1c2f4662ef1..1182c3d3569 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -466,4 +466,32 @@ ERROR 70100: Query execution was interrupted call bug6807()| ERROR 70100: Query execution was interrupted drop procedure bug6807| +drop procedure if exists bug8776_1| +drop procedure if exists bug8776_2| +drop procedure if exists bug8776_3| +drop procedure if exists bug8776_4| +create procedure bug8776_1() +begin +declare continue handler for sqlstate '42S0200test' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '42S0200test' +create procedure bug8776_2() +begin +declare continue handler for sqlstate '4200' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '4200' +create procedure bug8776_3() +begin +declare continue handler for sqlstate '420000' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '420000' +create procedure bug8776_4() +begin +declare continue handler for sqlstate '42x00' begin end; +begin end; +end| +ERROR 42000: Bad SQLSTATE: '42x00' drop table t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 594daf66fcb..0f775958d7a 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -641,6 +641,44 @@ call bug6807()| drop procedure bug6807| +# +# BUG#876: Stored Procedures: Invalid SQLSTATE is allowed in +# a DECLARE ? HANDLER FOR stmt. +# +--disable_warnings +drop procedure if exists bug8776_1| +drop procedure if exists bug8776_2| +drop procedure if exists bug8776_3| +drop procedure if exists bug8776_4| +--enable_warnings +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_1() +begin + declare continue handler for sqlstate '42S0200test' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_2() +begin + declare continue handler for sqlstate '4200' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_3() +begin + declare continue handler for sqlstate '420000' begin end; + begin end; +end| + +--error ER_SP_BAD_SQLSTATE +create procedure bug8776_4() +begin + declare continue handler for sqlstate '42x00' begin end; + begin end; +end| + drop table t1| diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5757510bfb4..ba4ef70486b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5326,3 +5326,5 @@ ER_PROC_AUTO_REVOKE_FAIL eng "Failed to revoke all privileges to dropped routine" ER_DATA_TOO_LONG 22001 eng "Data too long for column '%s' at row %ld" +ER_SP_BAD_SQLSTATE 42000 + eng "Bad SQLSTATE: '%s'" diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 7176498f276..15d3f87ff29 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -26,6 +26,30 @@ #include "sp_pcontext.h" #include "sp_head.h" +/* + * Sanity check for SQLSTATEs. Will not check if it's really an existing + * state (there are just too many), but will check length and bad characters. + * Returns TRUE if it's ok, FALSE if it's bad. + */ +bool +sp_cond_check(LEX_STRING *sqlstate) +{ + int i; + const char *p; + + if (sqlstate->length != 5) + return FALSE; + for (p= sqlstate->str, i= 0 ; i < 5 ; i++) + { + char c = p[i]; + + if ((c < '0' || '9' < c) && + (c < 'A' || 'Z' < c)) + return FALSE; + } + return TRUE; +} + sp_pcontext::sp_pcontext(sp_pcontext *prev) : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), m_handlers(0), m_parent(prev) diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 66f631f4938..42d8140b78c 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -60,6 +60,12 @@ typedef struct sp_cond_type uint mysqlerr; } sp_cond_type_t; +/* Sanity check for SQLSTATEs. Will not check if it's really an existing + * state (there are just too many), but will check length bad characters. + */ +extern bool +sp_cond_check(LEX_STRING *sqlstate); + typedef struct sp_cond { LEX_STRING name; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 45c3e94f0ff..a69b6a96982 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1760,13 +1760,15 @@ sp_cond: } | SQLSTATE_SYM opt_value TEXT_STRING_literal { /* SQLSTATE */ - uint len= ($3.length < sizeof($$->sqlstate)-1 ? - $3.length : sizeof($$->sqlstate)-1); - + if (!sp_cond_check(&$3)) + { + my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str); + YYABORT; + } $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$->type= sp_cond_type_t::state; - memcpy($$->sqlstate, $3.str, len); - $$->sqlstate[len]= '\0'; + memcpy($$->sqlstate, $3.str, 5); + $$->sqlstate[5]= '\0'; } ; |