Skip to content

Fixing conflict in lexer when '*/*' was in a query. #287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,18 +336,28 @@ public static function isComment($str, $end = false)
if ($len === 0) {
return null;
}

// If comment is Bash style (#):
if ($str[0] === '#') {
return Token::FLAG_COMMENT_BASH;
} elseif (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
return (($len > 2) && ($str[2] === '!')) ?
}
// If comment is opening C style (/*), warning, it could be a MySQL command (/*!)
if (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
return ($len > 2) && ($str[2] === '!') ?
Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
} elseif (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
}
// If comment is closing C style (*/), warning, it could conflicts with wildcard and a real opening C style.
// It would looks like the following valid SQL statement: "SELECT */* comment */ FROM...".
if (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
return Token::FLAG_COMMENT_C;
} elseif (($len > 2) && ($str[0] === '-')
}
// If comment is SQL style (--\s?):
if (($len > 2) && ($str[0] === '-')
&& ($str[1] === '-') && static::isWhitespace($str[2])
) {
return Token::FLAG_COMMENT_SQL;
} elseif (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
}
if (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
return Token::FLAG_COMMENT_SQL;
}

Expand Down
13 changes: 13 additions & 0 deletions src/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,19 @@ public function parseComment()
if (++$this->last < $this->len) {
$token .= $this->str[$this->last];
if (Context::isComment($token)) {
// There might be a conflict with "*" operator here, when string is "*/*".
// This can occurs in the following statements:
// - "SELECT */* comment */ FROM ..."
// - "SELECT 2*/* comment */3 AS `six`;"
$next = $this->last+1;
if (($next < $this->len) && $this->str[$next] === '*') {
// Conflict in "*/*": first "*" was not for ending a comment.
// Stop here and let other parsing method define the true behavior of that first star.
$this->last = $iBak;

return null;
}

$flags = Token::FLAG_COMMENT_C;

// This comment already ended. It may be a part of a
Expand Down
3 changes: 2 additions & 1 deletion tests/Lexer/LexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public function lexProvider()
array('lexer/lexWhitespace'),
array('lexer/lexLabel1'),
array('lexer/lexLabel2'),
array('lexer/lexNoLabel')
array('lexer/lexNoLabel'),
array('lexer/lexWildcardThenComment'),
);
}
}
33 changes: 33 additions & 0 deletions tests/data/lexer/lexWildcardThenComment.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
SELECT */* comment */

SELECT /* comment */*

SELECT 2*/* comment */3

SELECT 2/* comment */*3

SELECT */*
comment
on
multiple
lines
*/FROM

DELETE foo.*/* foo */ USING

DELETE foo.*/* foo */,bar.*/*bar*/ USING

SELECT `*`/*with comment*/ AS star_field

SELECT `*`,*/*with comment*/

DELETE a.*/*multi
line /* with C open tag
comment inside */ USING

SELECT 2*/* operator */3 + 3/* operator */*2,/* start wildcard */*/* end wildcard */

SELECT `*`/*a*/*/*b*/`*`

-- invalid queries
/* SELECT */*
Loading