From: Date: April 10 2009 4:23am Subject: bzr commit into mysql-5.1-bugteam branch (chad:2841) Bug#39559 List-Archive: http://lists.mysql.com/commits/71838 X-Bug: 39559 Message-Id: <1239330217.956227.27359.nullmailer@hypatia.cmiller> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0430367711==" --===============0430367711== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/cmiller/work/mysqlbzr/5.1-bugteam--bug39559/ based on revid:patrick.crews@stripped 2841 Chad MILLER 2009-04-09 Bug#39559: dump of stored procedures / functions with C-style \ comment can't be read back A change to the lexer in 5.1 caused slash-asterisk-bang-version sections to be terminated early if there exists a slash-asterisk- style comment inside it. Nesting comments is usually illegal, but we rely on versioned comment blocks in mysqldump, and the contents of those sections must be allowed to have comments. The problem was that when encountering open-comment tokens and consuming -or- passing through the contents, the "in_comment" state at the end was clobbered with the not-in-a-comment value, regardless of whether we were in a comment before this or not. So, """/*!VER one /* two */ three */""" would lose its in-comment state between "two" and "three". Save the echo and in-comment state, and restore it at the end of the comment if we consume a comment. modified: mysql-test/r/parser.result mysql-test/t/parser.test sql/sql_lex.cc sql/sql_lex.h === modified file 'mysql-test/r/parser.result' --- a/mysql-test/r/parser.result 2009-02-14 16:04:16 +0000 +++ b/mysql-test/r/parser.result 2009-04-10 02:18:18 +0000 @@ -615,3 +615,55 @@ UPDATE t3 SET a4={d '1789-07-14'} WHERE SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; a1 a4 DROP TABLE t1, t2, t3; +# +# Bug#39559: dump of stored procedures / functions with C-style +# comment can't be read back +# ++----------+--------+ +| expected | result | ++----------+--------+ +| 2 | 2 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 1 | 1 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 3 | 3 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 2 | 2 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 7 | 7 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 8 | 8 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 7 | 7 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 4 | 4 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 4 | 4 | ++----------+--------+ +# +# End of 5.1 tests +# === modified file 'mysql-test/t/parser.test' --- a/mysql-test/t/parser.test 2008-07-19 08:31:33 +0000 +++ b/mysql-test/t/parser.test 2009-04-10 02:18:18 +0000 @@ -724,3 +724,31 @@ SELECT {fn CONCAT(a1,a2)} FROM t1; UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; DROP TABLE t1, t2, t3; + +########################################################################### +--echo # +--echo # Bug#39559: dump of stored procedures / functions with C-style +--echo # comment can't be read back +--echo # + +--write_file $MYSQLTEST_VARDIR/tmp/bug39559.sql +select 2 as expected, /*!01000/**/*/ 2 as result; +select 1 as expected, /*!99998/**/*/ 1 as result; +select 3 as expected, /*!01000 1 + */ 2 as result; +select 2 as expected, /*!99990 1 + */ 2 as result; +select 7 as expected, /*!01000 1 + /* 8 + */ 2 + */ 4 as result; +select 8 as expected, /*!99998 1 + /* 2 + */ 4 + */ 8 as result; +select 7 as expected, /*!01000 1 + /*!01000 8 + */ 2 + */ 4 as result; +select 7 as expected, /*!01000 1 + /*!99998 8 + */ 2 + */ 4 as result; +select 4 as expected, /*!99998 1 + /*!99998 8 + */ 2 + */ 4 as result; +select 4 as expected, /*!99998 1 + /*!01000 8 + */ 2 + */ 4 as result; +select 7 as expected, /*!01000 1 + /*!01000 8 + /*!01000 error */ 16 + */ 2 + */ 4 as result; +select 4 as expected, /* 1 + /*!01000 8 + */ 2 + */ 4; +EOF + +--exec $MYSQL --comment --force --table test <$MYSQLTEST_VARDIR/tmp/bug39559.sql +--remove_file $MYSQLTEST_VARDIR/tmp/bug39559.sql + +--echo # +--echo # End of 5.1 tests +--echo # === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2009-03-05 14:22:33 +0000 +++ b/sql/sql_lex.cc 2009-04-10 02:18:18 +0000 @@ -712,6 +712,53 @@ static inline uint int_token(const char return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger; } + +/** + Given a stream that is advanced to the first contained character in + an open comment, consume the comment. Optionally, if we are allowed, + recurse so that we understand comments within this current comment. + + At this level, we do not support version-condition comments. We might + have been called with having just passed one in the stream, though. In + that case, we probably want to tolerate mundane comments inside. Thus, + the case for recursion. + + @retval Whether EOF reached before comment is closed. +*/ +bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted) +{ + reg1 uchar c; + while (! lip->eof()) + { + c= lip->yyGet(); + + if (remaining_recursions_permitted > 0) + { + if ((c == '/') && (lip->yyPeek() == '*')) + { + lip->yySkip(); /* Eat asterisk */ + consume_comment(lip, remaining_recursions_permitted-1); + continue; + } + } + + if (c == '*') + { + if (lip->yyPeek() == '/') + { + lip->yySkip(); /* Eat slash */ + return FALSE; + } + } + + if (c == '\n') + lip->yylineno++; + } + + return TRUE; +} + + /* MYSQLlex remember the following states from the following MYSQLlex() @@ -1204,6 +1251,8 @@ int MYSQLlex(void *arg, void *yythd) /* Reject '/' '*', since we might need to turn off the echo */ lip->yyUnget(); + lip->save_in_comment_state(); + if (lip->yyPeekn(2) == '!') { lip->in_comment= DISCARD_COMMENT; @@ -1246,11 +1295,17 @@ int MYSQLlex(void *arg, void *yythd) /* Expand the content of the special comment as real code */ lip->set_echo(TRUE); state=MY_LEX_START; - break; + break; /* Do not treat contents as a comment. */ + } + else + { + comment_closed= ! consume_comment(lip, 1); + /* version allowed to have one level of comment inside. */ } } else { + /* Not a version comment. */ state=MY_LEX_START; lip->set_echo(TRUE); break; @@ -1261,38 +1316,30 @@ int MYSQLlex(void *arg, void *yythd) lip->in_comment= PRESERVE_COMMENT; lip->yySkip(); // Accept / lip->yySkip(); // Accept * + comment_closed= ! consume_comment(lip, 0); + /* regular comments can have zero comments inside. */ } /* 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. + + Nesting regular comments isn't allowed. The first + '*' '/' returns the parser to the previous state. + + /#!VERSI oned containing /# regular #/ is allowed #/ + + Inside one versioned comment, another versioned comment + is treated as a regular discardable comment. It gets + no special parsing. */ - comment_closed= FALSE; - while (! lip->eof()) - { - c= lip->yyGet(); - if (c == '*') - { - if (lip->yyPeek() == '/') - { - lip->yySkip(); - comment_closed= TRUE; - state = MY_LEX_START; - break; - } - } - else if (c == '\n') - lip->yylineno++; - } + /* Unbalanced comments with a missing '*' '/' are a syntax error */ if (! comment_closed) return (ABORT_SYM); state = MY_LEX_START; // Try again - lip->in_comment= NO_COMMENT; - lip->set_echo(TRUE); + lip->restore_in_comment_state(); break; case MY_LEX_END_LONG_COMMENT: if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2009-03-05 14:22:33 +0000 +++ b/sql/sql_lex.h 2009-04-10 02:18:18 +0000 @@ -1160,6 +1160,18 @@ public: m_echo= echo; } + void save_in_comment_state() + { + m_echo_saved= m_echo; + in_comment_saved= in_comment; + } + + void restore_in_comment_state() + { + m_echo= m_echo_saved; + in_comment= in_comment_saved; + } + /** Skip binary from the input stream. @param n number of bytes to accept. @@ -1417,6 +1429,7 @@ private: /** Echo the parsed stream to the pre-processed buffer. */ bool m_echo; + bool m_echo_saved; /** Pre-processed buffer. */ char *m_cpp_buf; @@ -1479,6 +1492,7 @@ public: /** State of the lexical analyser for comments. */ enum_comment_state in_comment; + enum_comment_state in_comment_saved; /** Starting position of the TEXT_STRING or IDENT in the pre-processed --===============0430367711== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/chad@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: chad@stripped # target_branch: file:///home/cmiller/work/mysqlbzr/5.1-bugteam--\ # bug39559/ # testament_sha1: 3ab7c8f6c4f7dd0ff8ddce9f62c9accee619dccc # timestamp: 2009-04-09 22:23:37 -0400 # base_revision_id: patrick.crews@stripped\ # 6hahx3bk4u73h3dc # # Begin bundle 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 8D5e2CQmEDIGaAxAi/4u5IpwoSCa8SMW --===============0430367711==--