Skip to content

Commit beef18f

Browse files
niconoe-williamdes
authored andcommitted
Fixing conflict in lexer when '*/*' was in a query.
1 parent 2883365 commit beef18f

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

src/Context.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,28 @@ public static function isComment($str, $end = false)
336336
if ($len === 0) {
337337
return null;
338338
}
339+
340+
// If comment is Bash style (#):
339341
if ($str[0] === '#') {
340342
return Token::FLAG_COMMENT_BASH;
341-
} elseif (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
342-
return (($len > 2) && ($str[2] === '!')) ?
343+
}
344+
// If comment is opening C style (/*), warning, it could be a MySQL command (/*!)
345+
if (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
346+
return ($len > 2) && ($str[2] === '!') ?
343347
Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
344-
} elseif (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
348+
}
349+
// If comment is closing C style (*/), warning, it could conflicts with wildcard and a real opening C style.
350+
// It would looks like the following valid SQL statement: "SELECT */* comment */ FROM...".
351+
if (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
345352
return Token::FLAG_COMMENT_C;
346-
} elseif (($len > 2) && ($str[0] === '-')
353+
}
354+
// If comment is SQL style (--\s?):
355+
if (($len > 2) && ($str[0] === '-')
347356
&& ($str[1] === '-') && static::isWhitespace($str[2])
348357
) {
349358
return Token::FLAG_COMMENT_SQL;
350-
} elseif (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
359+
}
360+
if (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
351361
return Token::FLAG_COMMENT_SQL;
352362
}
353363

src/Lexer.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,19 @@ public function parseComment()
559559
if (++$this->last < $this->len) {
560560
$token .= $this->str[$this->last];
561561
if (Context::isComment($token)) {
562+
// There might be a conflict with "*" operator here, when string is "*/*".
563+
// This can occurs in the following statements:
564+
// - "SELECT */* comment */ FROM ..."
565+
// - "SELECT 2*/* comment */3 AS `six`;"
566+
$next = $this->last+1;
567+
if (($next < $this->len) && $this->str[$next] === '*') {
568+
// Conflict in "*/*": first "*" was not for ending a comment.
569+
// Stop here and let other parsing method define the true behavior of that first star.
570+
$this->last = $iBak;
571+
572+
return null;
573+
}
574+
562575
$flags = Token::FLAG_COMMENT_C;
563576

564577
// This comment already ended. It may be a part of a
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SELECT */* comment */
2+
SELECT /* comment */*
3+
SELECT 2*/* comment */3
4+
SELECT 2/* comment */*3
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
a:4:{s:5:"query";s:91:"SELECT */* comment */
2+
SELECT /* comment */*
3+
SELECT 2*/* comment */3
4+
SELECT 2/* comment */*3";s:5:"lexer";O:26:"PhpMyAdmin\SqlParser\Lexer":8:{s:3:"str";s:91:"SELECT */* comment */
5+
SELECT /* comment */*
6+
SELECT 2*/* comment */3
7+
SELECT 2/* comment */*3";s:3:"len";i:91;s:4:"last";i:91;s:4:"list";O:31:"PhpMyAdmin\SqlParser\TokensList":3:{s:6:"tokens";a:24:{i:0;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"SELECT";s:5:"value";s:6:"SELECT";s:7:"keyword";s:6:"SELECT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:0;}i:1;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:6;}i:2;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"*";s:5:"value";s:1:"*";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:1;s:8:"position";i:7;}i:3;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:13:"/* comment */";s:5:"value";s:13:"/* comment */";s:7:"keyword";N;s:4:"type";i:4;s:5:"flags";i:2;s:8:"position";i:8;}i:4;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
8+
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:21;}i:5;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"SELECT";s:5:"value";s:6:"SELECT";s:7:"keyword";s:6:"SELECT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:22;}i:6;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:28;}i:7;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:13:"/* comment */";s:5:"value";s:13:"/* comment */";s:7:"keyword";N;s:4:"type";i:4;s:5:"flags";i:2;s:8:"position";i:29;}i:8;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"*";s:5:"value";s:1:"*";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:1;s:8:"position";i:42;}i:9;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
9+
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:43;}i:10;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"SELECT";s:5:"value";s:6:"SELECT";s:7:"keyword";s:6:"SELECT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:44;}i:11;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:50;}i:12;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"2";s:5:"value";i:2;s:7:"keyword";N;s:4:"type";i:6;s:5:"flags";i:0;s:8:"position";i:51;}i:13;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"*";s:5:"value";s:1:"*";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:1;s:8:"position";i:52;}i:14;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:13:"/* comment */";s:5:"value";s:13:"/* comment */";s:7:"keyword";N;s:4:"type";i:4;s:5:"flags";i:2;s:8:"position";i:53;}i:15;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"3";s:5:"value";i:3;s:7:"keyword";N;s:4:"type";i:6;s:5:"flags";i:0;s:8:"position";i:66;}i:16;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"
10+
";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:67;}i:17;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:6:"SELECT";s:5:"value";s:6:"SELECT";s:7:"keyword";s:6:"SELECT";s:4:"type";i:1;s:5:"flags";i:3;s:8:"position";i:68;}i:18;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:" ";s:5:"value";s:1:" ";s:7:"keyword";N;s:4:"type";i:3;s:5:"flags";i:0;s:8:"position";i:74;}i:19;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"2";s:5:"value";i:2;s:7:"keyword";N;s:4:"type";i:6;s:5:"flags";i:0;s:8:"position";i:75;}i:20;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:13:"/* comment */";s:5:"value";s:13:"/* comment */";s:7:"keyword";N;s:4:"type";i:4;s:5:"flags";i:2;s:8:"position";i:76;}i:21;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"*";s:5:"value";s:1:"*";s:7:"keyword";N;s:4:"type";i:2;s:5:"flags";i:1;s:8:"position";i:89;}i:22;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";s:1:"3";s:5:"value";i:3;s:7:"keyword";N;s:4:"type";i:6;s:5:"flags";i:0;s:8:"position";i:90;}i:23;O:26:"PhpMyAdmin\SqlParser\Token":6:{s:5:"token";N;s:5:"value";N;s:7:"keyword";N;s:4:"type";i:9;s:5:"flags";i:0;s:8:"position";N;}}s:5:"count";i:24;s:3:"idx";i:0;}s:9:"delimiter";s:1:";";s:12:"delimiterLen";i:1;s:6:"strict";b:0;s:6:"errors";a:0:{}}s:6:"parser";N;s:6:"errors";a:2:{s:5:"lexer";a:0:{}s:6:"parser";a:0:{}}}

0 commit comments

Comments
 (0)