diff options
-rw-r--r-- | mysql-test/r/comments.result | 15 | ||||
-rw-r--r-- | mysql-test/t/comments.test | 33 | ||||
-rw-r--r-- | sql/sql_lex.cc | 37 |
3 files changed, 78 insertions, 7 deletions
diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result index a9106ce0538..1040c3fc8e9 100644 --- a/mysql-test/r/comments.result +++ b/mysql-test/r/comments.result @@ -26,3 +26,18 @@ select 1 # The rest of the row will be ignored 1 1 /* line with only comment */; +drop table if exists table_28779; +create table table_28779 (a int); +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';"; +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 '/*' AND b = 'bar'' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';*"; +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 '/*' AND b = 'bar';*' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;"; +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 '' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;*"; +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 ';*' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';"; +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 '/*!98765' AND b = 'bar'' at line 1 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';*"; +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 '/*!98765' AND b = 'bar';*' at line 1 +drop table table_28779; diff --git a/mysql-test/t/comments.test b/mysql-test/t/comments.test index 52273ec9523..0c6853cf298 100644 --- a/mysql-test/t/comments.test +++ b/mysql-test/t/comments.test @@ -19,3 +19,36 @@ select 1 # The rest of the row will be ignored /* line with only comment */; # End of 4.1 tests + + +# +# Bug#28779 (mysql_query() allows execution of statements with unbalanced +# comments) +# + +--disable_warnings +drop table if exists table_28779; +--enable_warnings + +create table table_28779 (a int); + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*' AND b = 'bar';*"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*! AND 2=2;*"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';"; + +--error 1064 +prepare bar from "DELETE FROM table_28779 WHERE a = 7 OR 1=1/*!98765' AND b = 'bar';*"; + +drop table table_28779; + diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7911da69862..1770ff358a2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -526,6 +526,7 @@ static inline uint int_token(const char *str,uint length) int MYSQLlex(void *arg, void *yythd) { reg1 uchar c; + bool comment_closed; int tokval, result_state; uint length; enum my_lex_states state; @@ -961,15 +962,34 @@ int MYSQLlex(void *arg, void *yythd) break; } } - while (lip->ptr != lip->end_of_query && - ((c=yyGet()) != '*' || yyPeek() != '/')) + /* + Discard: + - regular '/' '*' comments, + - special comments '/' '*' '!' for a future version, + by scanning until we find a closing '*' '/' marker. + Note: There is no such thing as nesting comments, + the first '*' '/' sequence seen will mark the end. + */ + comment_closed= FALSE; + while (lip->ptr != lip->end_of_query) { - if (c == '\n') - lip->yylineno++; + c= yyGet(); + if (c == '*') + { + if (yyPeek() == '/') + { + yySkip(); + comment_closed= TRUE; + state = MY_LEX_START; + break; + } + } + else if (c == '\n') + lip->yylineno++; } - if (lip->ptr != lip->end_of_query) - yySkip(); // remove last '/' - state = MY_LEX_START; // Try again + /* Unbalanced comments with a missing '*' '/' are a syntax error */ + if (! comment_closed) + return (ABORT_SYM); break; case MY_LEX_END_LONG_COMMENT: if (lex->in_comment && yyPeek() == '/') @@ -1009,6 +1029,9 @@ int MYSQLlex(void *arg, void *yythd) if (lip->ptr >= lip->end_of_query) { lip->next_state=MY_LEX_END; // Mark for next loop + /* Unbalanced comments with a missing '*' '/' are a syntax error */ + if (lex->in_comment) + return (ABORT_SYM); return(END_OF_INPUT); } state=MY_LEX_CHAR; |