Skip to content
Open
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
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ parameters:

-
message: "#^Parameter \\#1 \\$str of static method PhpMyAdmin\\\\SqlParser\\\\Context\\:\\:isSeparator\\(\\) expects string, mixed given\\.$#"
count: 4
count: 7
path: src/Lexer.php

-
Expand Down
17 changes: 5 additions & 12 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -695,21 +695,14 @@
<code>$this-&gt;last</code>
<code>$this-&gt;last</code>
</LoopInvalidation>
<MixedArrayAccess occurrences="43">
<code>$this-&gt;str[$this-&gt;last + 1]</code>
<code>$this-&gt;str[$this-&gt;last++]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<MixedArgument occurrences="3">
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
</MixedArgument>
<MixedArrayAccess occurrences="31">
<code>$this-&gt;str[$this-&gt;last + 1]</code>
<code>$this-&gt;str[$this-&gt;last++]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
<code>$this-&gt;str[$this-&gt;last]</code>
Expand Down
38 changes: 16 additions & 22 deletions src/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ public function parseNumber()
// or "E" causing wrongly interpreted scientific notation (".e[0 to 9]" is invalid). Such invalid notation could
// break the lexer when table names under a given database context starts with ".e[0-9]".
//
// Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
// Valid final states are: 2, 3, 4, 6, and 9. Any parsing that finished in a
// state other than these is invalid.
// Also, negative states are invalid states.
$iBak = $this->last;
Expand Down Expand Up @@ -886,29 +886,25 @@ public function parseNumber()
$state = 4;
} elseif ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
$state = 5;
} elseif (
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
$state = -$state;
break;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
if (! Context::isSeparator($this->str[$this->last])) {
// A number can't be directly followed by a letter _ or $
$state = -$state;
}

// Just digits and `.`, `e` and `E` are valid characters.
break;
}
} elseif ($state === 4) {
$flags |= Token::FLAG_NUMBER_FLOAT;
if ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
$state = 5;
} elseif (
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
$state = -$state;
break;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
if (! Context::isSeparator($this->str[$this->last])) {
// A number can't be directly followed by a letter _ or $
$state = -$state;
}

// Just digits, `e` and `E` are valid characters.
break;
}
Expand All @@ -919,14 +915,12 @@ public function parseNumber()
|| ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9')
) {
$state = 6;
} elseif (
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
) {
// A number can't be directly followed by a letter
$state = -$state;
break;
} else {
if (! Context::isSeparator($this->str[$this->last])) {
// A number can't be directly followed by a letter _ or $
$state = -$state;
}

break;
}
} elseif ($state === 6) {
Expand Down
1 change: 1 addition & 0 deletions tests/Lexer/LexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public static function lexProvider(): array
['lexer/lexKeyword'],
['lexer/lexKeyword2'],
['lexer/lexNumber'],
['lexer/lexNumberAtStartOfName'],
['lexer/lexOperator'],
['lexer/lexOperatorStarIsArithmetic'],
['lexer/lexOperatorStarIsWildcard'],
Expand Down
1 change: 1 addition & 0 deletions tests/data/lexer/lexNumberAtStartOfName.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO 2_bar SELECT 1;
124 changes: 124 additions & 0 deletions tests/data/lexer/lexNumberAtStartOfName.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"query": "INSERT INTO 2_bar SELECT 1;",
"lexer": {
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
"str": "INSERT INTO 2_bar SELECT 1;",
"len": 27,
"last": 27,
"list": {
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
"tokens": [
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "INSERT",
"value": "INSERT",
"keyword": "INSERT",
"type": 1,
"flags": 35,
"position": 0
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 6
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "INTO",
"value": "INTO",
"keyword": "INTO",
"type": 1,
"flags": 3,
"position": 7
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 11
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "2_bar",
"value": "2_bar",
"keyword": null,
"type": 0,
"flags": 0,
"position": 12
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 17
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "SELECT",
"value": "SELECT",
"keyword": "SELECT",
"type": 1,
"flags": 3,
"position": 18
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": " ",
"value": " ",
"keyword": null,
"type": 3,
"flags": 0,
"position": 24
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": "1",
"value": 1,
"keyword": null,
"type": 6,
"flags": 0,
"position": 25
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": ";",
"value": ";",
"keyword": null,
"type": 9,
"flags": 0,
"position": 26
},
{
"@type": "PhpMyAdmin\\SqlParser\\Token",
"token": null,
"value": null,
"keyword": null,
"type": 9,
"flags": 0,
"position": null
}
],
"count": 11,
"idx": 0
},
"delimiter": ";",
"delimiterLen": 1,
"strict": false,
"errors": []
},
"parser": null,
"errors": {
"lexer": [],
"parser": []
}
}