From 30925cd49826c59ea8459a24bcb24d47c2ce562d Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Mon, 4 Apr 2016 23:45:10 +0200 Subject: [PATCH] Fixed bug #71447 (Quotes inside comments not properly handled) --- NEWS | 2 + ext/pdo/pdo_sql_parser.c | 204 ++++++++++++++--------------------- ext/pdo/pdo_sql_parser.re | 2 +- ext/pdo/tests/bug_71447.phpt | 104 ++++++++++++++++++ 4 files changed, 187 insertions(+), 125 deletions(-) create mode 100644 ext/pdo/tests/bug_71447.phpt diff --git a/NEWS b/NEWS index 8653e4dc75..0f9594ec8a 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,8 @@ PHP NEWS - PDO: . Fixed bug #52098 (Own PDOStatement implementation ignore __call()). (Daniel kalaspuffar, Julien) + . Fixed bug #71447 (Quotes inside comments not properly handled). + (Matteo) - Postgres: . Fixed bug #71820 (pg_fetch_object binds parameters before call diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 22fd696155..5a419782b5 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -54,7 +54,6 @@ static int scan(Scanner *s) #line 55 "ext/pdo/pdo_sql_parser.c" { YYCTYPE yych; - unsigned int yyaccept = 0; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; @@ -62,31 +61,32 @@ static int scan(Scanner *s) case 0x00: goto yy2; case '"': goto yy3; case '\'': goto yy5; - case '-': goto yy11; - case '/': goto yy9; + case '(': + case ')': + case '*': + case '+': + case ',': + case '.': goto yy9; + case '-': goto yy10; + case '/': goto yy11; case ':': goto yy6; case '?': goto yy7; default: goto yy12; } yy2: YYCURSOR = YYMARKER; - switch (yyaccept) { - case 0: goto yy4; - case 1: goto yy10; - } + goto yy4; yy3: - yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if (yych >= 0x01) goto yy43; + if (yych >= 0x01) goto yy37; yy4: #line 63 "ext/pdo/pdo_sql_parser.re" { SKIP_ONE(PDO_PARSER_TEXT); } -#line 85 "ext/pdo/pdo_sql_parser.c" +#line 86 "ext/pdo/pdo_sql_parser.c" yy5: - yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 0x00) goto yy4; - goto yy38; + goto yy32; yy6: yych = *++YYCURSOR; switch (yych) { @@ -152,14 +152,14 @@ yy6: case 'w': case 'x': case 'y': - case 'z': goto yy32; - case ':': goto yy35; + case 'z': goto yy26; + case ':': goto yy29; default: goto yy4; } yy7: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case '?': goto yy29; + case '?': goto yy23; default: goto yy8; } yy8: @@ -167,133 +167,89 @@ yy8: { RET(PDO_PARSER_BIND_POS); } #line 169 "ext/pdo/pdo_sql_parser.c" yy9: - ++YYCURSOR; - switch ((yych = *YYCURSOR)) { - case '*': goto yy19; - default: goto yy13; - } + yych = *++YYCURSOR; + goto yy4; yy10: -#line 65 "ext/pdo/pdo_sql_parser.re" - { RET(PDO_PARSER_TEXT); } -#line 179 "ext/pdo/pdo_sql_parser.c" -yy11: yych = *++YYCURSOR; switch (yych) { - case '-': goto yy14; - default: goto yy13; + case '-': goto yy21; + default: goto yy4; + } +yy11: + yych = *(YYMARKER = ++YYCURSOR); + switch (yych) { + case '*': goto yy15; + default: goto yy4; } yy12: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy13: switch (yych) { case 0x00: case '"': case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': case ':': - case '?': goto yy10; + case '?': goto yy14; default: goto yy12; } yy14: +#line 65 "ext/pdo/pdo_sql_parser.re" + { RET(PDO_PARSER_TEXT); } +#line 208 "ext/pdo/pdo_sql_parser.c" +yy15: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case 0x00: - case '"': - case '\'': - case ':': - case '?': goto yy17; - case '\n': - case '\r': goto yy12; - default: goto yy14; + case '*': goto yy17; + default: goto yy15; } -yy16: -#line 64 "ext/pdo/pdo_sql_parser.re" - { RET(PDO_PARSER_TEXT); } -#line 216 "ext/pdo/pdo_sql_parser.c" yy17: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case '\n': - case '\r': goto yy16; - default: goto yy17; + case '*': goto yy17; + case '/': goto yy19; + default: goto yy15; } yy19: - yyaccept = 1; - YYMARKER = ++YYCURSOR; - if (YYLIMIT <= YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch (yych) { - case 0x00: - case '"': - case '\'': - case ':': - case '?': goto yy21; - case '*': goto yy23; - default: goto yy19; - } + ++YYCURSOR; +yy20: +#line 64 "ext/pdo/pdo_sql_parser.re" + { RET(PDO_PARSER_TEXT); } +#line 231 "ext/pdo/pdo_sql_parser.c" yy21: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case '*': goto yy26; + case '\n': + case '\r': goto yy20; default: goto yy21; } yy23: - yyaccept = 1; - YYMARKER = ++YYCURSOR; - if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch (yych) { - case 0x00: - case '"': - case '\'': - case ':': - case '?': goto yy21; - case '*': goto yy23; - case '/': goto yy25; - default: goto yy19; - } -yy25: - yych = *++YYCURSOR; - switch (yych) { - case 0x00: - case '"': - case '\'': - case ':': - case '?': goto yy16; - default: goto yy12; - } -yy26: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case '*': goto yy26; - case '/': goto yy28; - default: goto yy21; + case '?': goto yy23; + default: goto yy25; } -yy28: - yych = *++YYCURSOR; - goto yy16; -yy29: - ++YYCURSOR; - if (YYLIMIT <= YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch (yych) { - case '?': goto yy29; - default: goto yy31; - } -yy31: +yy25: #line 60 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 296 "ext/pdo/pdo_sql_parser.c" -yy32: +#line 252 "ext/pdo/pdo_sql_parser.c" +yy26: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; @@ -360,65 +316,65 @@ yy32: case 'w': case 'x': case 'y': - case 'z': goto yy32; - default: goto yy34; + case 'z': goto yy26; + default: goto yy28; } -yy34: +yy28: #line 61 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND); } -#line 370 "ext/pdo/pdo_sql_parser.c" -yy35: +#line 326 "ext/pdo/pdo_sql_parser.c" +yy29: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case ':': goto yy35; - default: goto yy31; + case ':': goto yy29; + default: goto yy25; } -yy37: +yy31: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy38: +yy32: switch (yych) { case 0x00: goto yy2; - case '\'': goto yy40; - case '\\': goto yy39; - default: goto yy37; + case '\'': goto yy34; + case '\\': goto yy33; + default: goto yy31; } -yy39: +yy33: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yych <= 0x00) goto yy2; - goto yy37; -yy40: + goto yy31; +yy34: ++YYCURSOR; #line 59 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 400 "ext/pdo/pdo_sql_parser.c" -yy42: +#line 356 "ext/pdo/pdo_sql_parser.c" +yy36: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy43: +yy37: switch (yych) { case 0x00: goto yy2; - case '"': goto yy45; - case '\\': goto yy44; - default: goto yy42; + case '"': goto yy39; + case '\\': goto yy38; + default: goto yy36; } -yy44: +yy38: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yych <= 0x00) goto yy2; - goto yy42; -yy45: + goto yy36; +yy39: ++YYCURSOR; #line 58 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 422 "ext/pdo/pdo_sql_parser.c" +#line 378 "ext/pdo/pdo_sql_parser.c" } #line 66 "ext/pdo/pdo_sql_parser.re" diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index 0bf7bffaec..bed5befa87 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -49,7 +49,7 @@ static int scan(Scanner *s) BINDCHR = [:][a-zA-Z0-9_]+; QUESTION = [?]; COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*); - SPECIALS = [:?"']; + SPECIALS = [:?"'-/]; MULTICHAR = ([:]{2,}|[?]{2,}); ANYNOEOF = [\001-\377]; */ diff --git a/ext/pdo/tests/bug_71447.phpt b/ext/pdo/tests/bug_71447.phpt new file mode 100644 index 0000000000..8b5c0732f1 --- /dev/null +++ b/ext/pdo/tests/bug_71447.phpt @@ -0,0 +1,104 @@ +--TEST-- +PDO Common: Bug #71447 (Quotes inside comments not properly handled) +--SKIPIF-- + +--FILE-- +setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING); +$db->setAttribute (\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_NUM); +$db->setAttribute (\PDO::ATTR_EMULATE_PREPARES, false); +$db->exec('CREATE TABLE test(id int)'); +$db->exec('INSERT INTO test VALUES(1)'); + +// Comment without quotes or placeholders +$stmt = $db->prepare(" + SELECT -- Thats all folks! + '\"abc\":8000' + FROM test +"); + +$stmt->execute(); +var_dump($stmt->fetchColumn()); + +// Comment and placeholder within a string +$stmt = $db->prepare(" + SELECT + '\"abc\":8001 -- Wat?' + FROM test +"); + +$stmt->execute(); +var_dump($stmt->fetchColumn()); + +// Comment with single quote +$stmt = $db->prepare(" + SELECT -- That's all folks! + '\"abc\":8002' + FROM test +"); + +$stmt->execute(); +var_dump($stmt->fetchColumn()); + +// C-Style comment with single quote +$stmt = $db->prepare(" + SELECT /* That's all folks! */ + '\"abc\":8003' + FROM test +"); + +$stmt->execute(); +var_dump($stmt->fetchColumn()); + +// Comment with double quote +$stmt = $db->prepare(" + SELECT -- Is it only \"single quotes? + '\"abc\":8004' + FROM test +"); + +$stmt->execute(); +var_dump($stmt->fetchColumn()); + +// Comment with ? placeholder +$stmt = $db->prepare(" + SELECT -- What about question marks here? + * + FROM test + WHERE id = ? +"); + +$stmt->execute([1]); +var_dump($stmt->fetchColumn()); + +// Comment with named placeholder +$stmt = $db->prepare(" + SELECT -- What about placeholders :bar + * + FROM test + WHERE id = :id +"); + +$stmt->execute(['id' => 1]); +var_dump($stmt->fetchColumn()); + + +?> +--EXPECT-- +string(10) ""abc":8000" +string(18) ""abc":8001 -- Wat?" +string(10) ""abc":8002" +string(10) ""abc":8003" +string(10) ""abc":8004" +string(1) "1" +string(1) "1" -- 2.40.0