summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/comments.result15
-rw-r--r--mysql-test/t/comments.test33
-rw-r--r--sql/sql_lex.cc37
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;