Bug#28779 (mysql_query() allows execution of statements with unbalanced

comments)

Before this fix, the server would accept queries that contained comments,
even when the comments were not properly closed with a '*' '/' marker.

For example,
  select 1 /* + 2 <EOF>
would be accepted as
  select 1 /* + 2 */ <EOF>
and executed as
  select 1

With this fix, the server now rejects queries with unclosed comments
as syntax errors.
Both regular comments ('/' '*') and special comments ('/' '*' '!') must be
closed with '*' '/' to be parsed correctly.
parent 290d7249
...@@ -26,3 +26,18 @@ select 1 # The rest of the row will be ignored ...@@ -26,3 +26,18 @@ select 1 # The rest of the row will be ignored
1 1
1 1
/* line with only comment */; /* 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;
...@@ -19,3 +19,36 @@ select 1 # The rest of the row will be ignored ...@@ -19,3 +19,36 @@ select 1 # The rest of the row will be ignored
/* line with only comment */; /* line with only comment */;
# End of 4.1 tests # 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;
...@@ -526,6 +526,7 @@ static inline uint int_token(const char *str,uint length) ...@@ -526,6 +526,7 @@ static inline uint int_token(const char *str,uint length)
int MYSQLlex(void *arg, void *yythd) int MYSQLlex(void *arg, void *yythd)
{ {
reg1 uchar c; reg1 uchar c;
bool comment_closed;
int tokval, result_state; int tokval, result_state;
uint length; uint length;
enum my_lex_states state; enum my_lex_states state;
...@@ -961,15 +962,34 @@ int MYSQLlex(void *arg, void *yythd) ...@@ -961,15 +962,34 @@ int MYSQLlex(void *arg, void *yythd)
break; 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') c= yyGet();
lip->yylineno++; 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) /* Unbalanced comments with a missing '*' '/' are a syntax error */
yySkip(); // remove last '/' if (! comment_closed)
state = MY_LEX_START; // Try again return (ABORT_SYM);
break; break;
case MY_LEX_END_LONG_COMMENT: case MY_LEX_END_LONG_COMMENT:
if (lex->in_comment && yyPeek() == '/') if (lex->in_comment && yyPeek() == '/')
...@@ -1009,6 +1029,9 @@ int MYSQLlex(void *arg, void *yythd) ...@@ -1009,6 +1029,9 @@ int MYSQLlex(void *arg, void *yythd)
if (lip->ptr >= lip->end_of_query) if (lip->ptr >= lip->end_of_query)
{ {
lip->next_state=MY_LEX_END; // Mark for next loop 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); return(END_OF_INPUT);
} }
state=MY_LEX_CHAR; state=MY_LEX_CHAR;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment