summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
author <anders.song@greatopensource.com>2011-01-15 13:48:16 +0800
committer <anders.song@greatopensource.com>2011-01-15 13:48:16 +0800
commitade1c74b3f9b662a572b843b7090fc68c5777ca9 (patch)
tree47cd4d625ae5d451bf005ef0bcb792887b74d631 /sql/sql_lex.cc
parent0355456dfbe077f55981bf03b9a1ce3c1622d3df (diff)
downloadmariadb-git-ade1c74b3f9b662a572b843b7090fc68c5777ca9.tar.gz
BUG#49124 Security issue with /*!-versioned */ SQL statements on Slave
Backport to 5.0. /*![:version:] Query Code */, where [:version:] is a sequence of 5 digits representing the mysql server version(e.g /*!50200 ... */), is a special comment that the query in it can be executed on those servers whose versions are larger than the version appearing in the comment. It leads to a security issue when slave's version is larger than master's. A malicious user can improve his privileges on slaves. Because slave SQL thread is running with SUPER privileges, so it can execute queries that he/she does not have privileges on master. This bug is fixed with the logic below: - To replace '!' with ' ' in the magic comments which are not applied on master. So they become common comments and will not be applied on slave. - Example: 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*!99999 ,(3)*/ will be binlogged as 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /* 99999 ,(3)*/
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc25
1 files changed, 22 insertions, 3 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 17ee53d446b..a013d5466c1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -109,7 +109,7 @@ st_parsing_options::reset()
}
Lex_input_stream::Lex_input_stream(THD *thd,
- const char* buffer,
+ char* buffer,
unsigned int length)
: m_thd(thd),
yylineno(1),
@@ -580,7 +580,7 @@ int MYSQLlex(void *arg, void *yythd)
state=MY_LEX_COMMENT;
break;
}
- yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr
+ yylval->lex_str.str=lip->ptr=(char*)lip->tok_start;// Set to first chr
yylval->lex_str.length=1;
c=yyGet();
if (c != ')')
@@ -946,6 +946,9 @@ int MYSQLlex(void *arg, void *yythd)
state = MY_LEX_START; // Try again
break;
case MY_LEX_LONG_COMMENT: /* Long C comment? */
+ {
+ char *version_mark= NULL;
+
if (yyPeek() != '*')
{
state=MY_LEX_CHAR; // Probable division
@@ -956,6 +959,8 @@ int MYSQLlex(void *arg, void *yythd)
if (yyPeek() == '!') // MySQL command in comment
{
ulong version=MYSQL_VERSION_ID;
+ version_mark= lip->ptr;
+
yySkip();
state=MY_LEX_START;
if (my_isdigit(cs,yyPeek()))
@@ -964,9 +969,18 @@ int MYSQLlex(void *arg, void *yythd)
}
if (version <= MYSQL_VERSION_ID)
{
- lex->in_comment=1;
+ lex->in_comment=1;
+ version_mark= NULL;
break;
}
+ else
+ {
+ /*
+ Patch and skip the conditional comment to avoid it
+ being propagated infinitely (eg. to a slave).
+ */
+ *version_mark= ' ';
+ }
}
/*
Discard:
@@ -995,8 +1009,13 @@ int MYSQLlex(void *arg, void *yythd)
}
/* Unbalanced comments with a missing '*' '/' are a syntax error */
if (! comment_closed)
+ {
+ if (version_mark != NULL)
+ *version_mark= '!';
return (ABORT_SYM);
+ }
break;
+ }
case MY_LEX_END_LONG_COMMENT:
if (lex->in_comment && yyPeek() == '/')
{