Skip to content

Commit e08e9d2

Browse files
committed
Merge #632 - Fix lex number at start of name followed by _ or $
Pull-request: #632 Fixes: #607 Signed-off-by: William Desportes <williamdes@wdes.fr>
2 parents 3028598 + b61f7af commit e08e9d2

6 files changed

Lines changed: 148 additions & 35 deletions

File tree

‎phpstan-baseline.neon‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ parameters:
10521052

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

10581058
-

‎psalm-baseline.xml‎

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -731,21 +731,14 @@
731731
<code>$this-&gt;last</code>
732732
<code>$this-&gt;last</code>
733733
</LoopInvalidation>
734-
<MixedArrayAccess occurrences="43">
735-
<code>$this-&gt;str[$this-&gt;last + 1]</code>
736-
<code>$this-&gt;str[$this-&gt;last++]</code>
737-
<code>$this-&gt;str[$this-&gt;last]</code>
738-
<code>$this-&gt;str[$this-&gt;last]</code>
739-
<code>$this-&gt;str[$this-&gt;last]</code>
740-
<code>$this-&gt;str[$this-&gt;last]</code>
741-
<code>$this-&gt;str[$this-&gt;last]</code>
742-
<code>$this-&gt;str[$this-&gt;last]</code>
743-
<code>$this-&gt;str[$this-&gt;last]</code>
744-
<code>$this-&gt;str[$this-&gt;last]</code>
745-
<code>$this-&gt;str[$this-&gt;last]</code>
734+
<MixedArgument occurrences="3">
746735
<code>$this-&gt;str[$this-&gt;last]</code>
747736
<code>$this-&gt;str[$this-&gt;last]</code>
748737
<code>$this-&gt;str[$this-&gt;last]</code>
738+
</MixedArgument>
739+
<MixedArrayAccess occurrences="31">
740+
<code>$this-&gt;str[$this-&gt;last + 1]</code>
741+
<code>$this-&gt;str[$this-&gt;last++]</code>
749742
<code>$this-&gt;str[$this-&gt;last]</code>
750743
<code>$this-&gt;str[$this-&gt;last]</code>
751744
<code>$this-&gt;str[$this-&gt;last]</code>

‎src/Lexer.php‎

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ public function parseNumber()
853853
// or "E" causing wrongly interpreted scientific notation (".e[0 to 9]" is invalid). Such invalid notation could
854854
// break the lexer when table names under a given database context starts with ".e[0-9]".
855855
//
856-
// Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
856+
// Valid final states are: 2, 3, 4, 6, and 9. Any parsing that finished in a
857857
// state other than these is invalid.
858858
// Also, negative states are invalid states.
859859
$iBak = $this->last;
@@ -897,29 +897,25 @@ public function parseNumber()
897897
$state = 4;
898898
} elseif ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
899899
$state = 5;
900-
} elseif (
901-
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
902-
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
903-
) {
904-
// A number can't be directly followed by a letter
905-
$state = -$state;
906-
break;
907900
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
901+
if (! Context::isSeparator($this->str[$this->last])) {
902+
// A number can't be directly followed by a letter _ or $
903+
$state = -$state;
904+
}
905+
908906
// Just digits and `.`, `e` and `E` are valid characters.
909907
break;
910908
}
911909
} elseif ($state === 4) {
912910
$flags |= Token::FLAG_NUMBER_FLOAT;
913911
if ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
914912
$state = 5;
915-
} elseif (
916-
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
917-
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
918-
) {
919-
// A number can't be directly followed by a letter
920-
$state = -$state;
921-
break;
922913
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
914+
if (! Context::isSeparator($this->str[$this->last])) {
915+
// A number can't be directly followed by a letter _ or $
916+
$state = -$state;
917+
}
918+
923919
// Just digits, `e` and `E` are valid characters.
924920
break;
925921
}
@@ -930,14 +926,12 @@ public function parseNumber()
930926
|| ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9')
931927
) {
932928
$state = 6;
933-
} elseif (
934-
($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
935-
|| ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
936-
) {
937-
// A number can't be directly followed by a letter
938-
$state = -$state;
939-
break;
940929
} else {
930+
if (! Context::isSeparator($this->str[$this->last])) {
931+
// A number can't be directly followed by a letter _ or $
932+
$state = -$state;
933+
}
934+
941935
break;
942936
}
943937
} elseif ($state === 6) {

‎tests/Lexer/LexerTest.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public static function lexProvider(): array
8282
['lexer/lexKeyword'],
8383
['lexer/lexKeyword2'],
8484
['lexer/lexNumber'],
85+
['lexer/lexNumberAtStartOfName'],
8586
['lexer/lexOperator'],
8687
['lexer/lexOperatorStarIsArithmetic'],
8788
['lexer/lexOperatorStarIsWildcard'],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
INSERT INTO 2_bar SELECT 1;
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
{
2+
"query": "INSERT INTO 2_bar SELECT 1;",
3+
"lexer": {
4+
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
5+
"str": "INSERT INTO 2_bar SELECT 1;",
6+
"len": 27,
7+
"last": 27,
8+
"list": {
9+
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
10+
"tokens": [
11+
{
12+
"@type": "PhpMyAdmin\\SqlParser\\Token",
13+
"token": "INSERT",
14+
"value": "INSERT",
15+
"keyword": "INSERT",
16+
"type": 1,
17+
"flags": 35,
18+
"position": 0
19+
},
20+
{
21+
"@type": "PhpMyAdmin\\SqlParser\\Token",
22+
"token": " ",
23+
"value": " ",
24+
"keyword": null,
25+
"type": 3,
26+
"flags": 0,
27+
"position": 6
28+
},
29+
{
30+
"@type": "PhpMyAdmin\\SqlParser\\Token",
31+
"token": "INTO",
32+
"value": "INTO",
33+
"keyword": "INTO",
34+
"type": 1,
35+
"flags": 3,
36+
"position": 7
37+
},
38+
{
39+
"@type": "PhpMyAdmin\\SqlParser\\Token",
40+
"token": " ",
41+
"value": " ",
42+
"keyword": null,
43+
"type": 3,
44+
"flags": 0,
45+
"position": 11
46+
},
47+
{
48+
"@type": "PhpMyAdmin\\SqlParser\\Token",
49+
"token": "2_bar",
50+
"value": "2_bar",
51+
"keyword": null,
52+
"type": 0,
53+
"flags": 0,
54+
"position": 12
55+
},
56+
{
57+
"@type": "PhpMyAdmin\\SqlParser\\Token",
58+
"token": " ",
59+
"value": " ",
60+
"keyword": null,
61+
"type": 3,
62+
"flags": 0,
63+
"position": 17
64+
},
65+
{
66+
"@type": "PhpMyAdmin\\SqlParser\\Token",
67+
"token": "SELECT",
68+
"value": "SELECT",
69+
"keyword": "SELECT",
70+
"type": 1,
71+
"flags": 3,
72+
"position": 18
73+
},
74+
{
75+
"@type": "PhpMyAdmin\\SqlParser\\Token",
76+
"token": " ",
77+
"value": " ",
78+
"keyword": null,
79+
"type": 3,
80+
"flags": 0,
81+
"position": 24
82+
},
83+
{
84+
"@type": "PhpMyAdmin\\SqlParser\\Token",
85+
"token": "1",
86+
"value": 1,
87+
"keyword": null,
88+
"type": 6,
89+
"flags": 0,
90+
"position": 25
91+
},
92+
{
93+
"@type": "PhpMyAdmin\\SqlParser\\Token",
94+
"token": ";",
95+
"value": ";",
96+
"keyword": null,
97+
"type": 9,
98+
"flags": 0,
99+
"position": 26
100+
},
101+
{
102+
"@type": "PhpMyAdmin\\SqlParser\\Token",
103+
"token": null,
104+
"value": null,
105+
"keyword": null,
106+
"type": 9,
107+
"flags": 0,
108+
"position": null
109+
}
110+
],
111+
"count": 11,
112+
"idx": 0
113+
},
114+
"delimiter": ";",
115+
"delimiterLen": 1,
116+
"strict": false,
117+
"errors": []
118+
},
119+
"parser": null,
120+
"errors": {
121+
"lexer": [],
122+
"parser": []
123+
}
124+
}

0 commit comments

Comments
 (0)