From 27c803aaed259f76a66db1278eea05f30a8ec956 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 20 Aug 2013 19:19:02 +0200 Subject: [PATCH] Fix bug #64953 (Postgres prepared statement positional parameter casting) --- NEWS | 4 ++ ext/pdo/pdo_sql_parser.c | 63 ++++++++++++++------------- ext/pdo/pdo_sql_parser.re | 4 +- ext/pdo_pgsql/tests/bug64953.phpt | 71 +++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 ext/pdo_pgsql/tests/bug64953.phpt diff --git a/NEWS b/NEWS index aeae233dc8..1218c5069a 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,10 @@ PHP NEWS - SPL: . Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence) +- PDO: + . Fixed bug #64953 (Postgres prepared statement positional parameter + casting). (Mike) + - Phar: . Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for some specific contents). (Stas) diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 4c523506c4..1ed78c1cc5 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Thu Apr 19 12:42:11 2012 */ +/* Generated by re2c 0.13.5 on Tue Aug 20 18:02:48 2013 */ #line 1 "ext/pdo/pdo_sql_parser.re" /* +----------------------------------------------------------------------+ @@ -77,7 +77,7 @@ yy2: yy3: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if (yych >= 0x01) goto yy41; + if (yych >= 0x01) goto yy43; yy4: #line 63 "ext/pdo/pdo_sql_parser.re" { SKIP_ONE(PDO_PARSER_TEXT); } @@ -86,7 +86,7 @@ yy5: yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 0x00) goto yy4; - goto yy36; + goto yy38; yy6: yych = *++YYCURSOR; switch (yych) { @@ -153,21 +153,19 @@ yy6: case 'x': case 'y': case 'z': goto yy32; - case ':': - case '?': goto yy29; + case ':': goto yy35; default: goto yy4; } yy7: ++YYCURSOR; switch ((yych = *YYCURSOR)) { - case ':': case '?': goto yy29; default: goto yy8; } yy8: #line 62 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND_POS); } -#line 171 "ext/pdo/pdo_sql_parser.c" +#line 169 "ext/pdo/pdo_sql_parser.c" yy9: ++YYCURSOR; switch ((yych = *YYCURSOR)) { @@ -177,7 +175,7 @@ yy9: yy10: #line 65 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 181 "ext/pdo/pdo_sql_parser.c" +#line 179 "ext/pdo/pdo_sql_parser.c" yy11: yych = *++YYCURSOR; switch (yych) { @@ -214,7 +212,7 @@ yy14: yy16: #line 64 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 218 "ext/pdo/pdo_sql_parser.c" +#line 216 "ext/pdo/pdo_sql_parser.c" yy17: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -288,14 +286,13 @@ yy29: if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; switch (yych) { - case ':': case '?': goto yy29; default: goto yy31; } yy31: #line 60 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 299 "ext/pdo/pdo_sql_parser.c" +#line 296 "ext/pdo/pdo_sql_parser.c" yy32: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -369,51 +366,59 @@ yy32: yy34: #line 61 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND); } -#line 373 "ext/pdo/pdo_sql_parser.c" +#line 370 "ext/pdo/pdo_sql_parser.c" yy35: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy36: switch (yych) { - case 0x00: goto yy2; - case '\'': goto yy38; - case '\\': goto yy37; - default: goto yy35; + case ':': goto yy35; + default: goto yy31; } yy37: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - if (yych <= 0x00) goto yy2; - goto yy35; yy38: + switch (yych) { + case 0x00: goto yy2; + case '\'': goto yy40; + case '\\': goto yy39; + default: goto yy37; + } +yy39: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy2; + goto yy37; +yy40: ++YYCURSOR; #line 59 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 395 "ext/pdo/pdo_sql_parser.c" -yy40: +#line 400 "ext/pdo/pdo_sql_parser.c" +yy42: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy41: +yy43: switch (yych) { case 0x00: goto yy2; - case '"': goto yy43; - case '\\': goto yy42; - default: goto yy40; + case '"': goto yy45; + case '\\': goto yy44; + default: goto yy42; } -yy42: +yy44: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; if (yych <= 0x00) goto yy2; - goto yy40; -yy43: + goto yy42; +yy45: ++YYCURSOR; #line 58 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 417 "ext/pdo/pdo_sql_parser.c" +#line 422 "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 80e3b4f95f..1936a37340 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -50,14 +50,14 @@ static int scan(Scanner *s) QUESTION = [?]; COMMENTS = ("/*"([^*]+|[*]+[^/*])*[*]*"*/"|"--"[^\r\n]*); SPECIALS = [:?"']; - MULTICHAR = [:?]; + MULTICHAR = ([:]{2,}|[?]{2,}); ANYNOEOF = [\001-\377]; */ /*!re2c (["](([\\]ANYNOEOF)|ANYNOEOF\["\\])*["]) { RET(PDO_PARSER_TEXT); } (['](([\\]ANYNOEOF)|ANYNOEOF\['\\])*[']) { RET(PDO_PARSER_TEXT); } - MULTICHAR{2,} { RET(PDO_PARSER_TEXT); } + MULTICHAR { RET(PDO_PARSER_TEXT); } BINDCHR { RET(PDO_PARSER_BIND); } QUESTION { RET(PDO_PARSER_BIND_POS); } SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); } diff --git a/ext/pdo_pgsql/tests/bug64953.phpt b/ext/pdo_pgsql/tests/bug64953.phpt new file mode 100644 index 0000000000..6e72bcab68 --- /dev/null +++ b/ext/pdo_pgsql/tests/bug64953.phpt @@ -0,0 +1,71 @@ +--TEST-- +PDO PgSQL Bug #64953 (Postgres prepared statement positional parameter casting) +--SKIPIF-- + +--FILE-- +setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + +echo "Taken from the bug report:\n"; + +$st = $pdo->prepare('SELECT ?::char as i'); +$st->bindValue(1, '1'); +$st->execute(); +var_dump($st->fetch()); // return false + + +$st = $pdo->prepare('SELECT (?)::char as i'); +$st->bindValue(1, '1'); +$st->execute(); +var_dump($st->fetch()); // return array(1) { ["i"]=> string(1) "1" } + +echo "Something more nasty:\n"; + +$st = $pdo->prepare("SELECT :int::int as i"); +$st->execute(array(":int" => 123)); +var_dump($st->fetch()); + +$st = $pdo->prepare("SELECT '''?'''::text as \":text\""); +$st->execute(); +var_dump($st->fetch()); + +?> +Done +--EXPECT-- +Test +Taken from the bug report: +array(2) { + ["i"]=> + string(1) "1" + [0]=> + string(1) "1" +} +array(2) { + ["i"]=> + string(1) "1" + [0]=> + string(1) "1" +} +Something more nasty: +array(2) { + ["i"]=> + string(3) "123" + [0]=> + string(3) "123" +} +array(2) { + [":text"]=> + string(3) "'?'" + [0]=> + string(3) "'?'" +} +Done -- 2.40.0