ID: 44251 Comment by: tsteiner at nerdclub dot net Reported By: om at viazenetti dot de Status: Open Bug Type: PDO related Operating System: Linux PHP Version: 5.2.5 New Comment:
Here's a patch to PHP 5.2.6 that seems to both fix this bug and not affect the test case in Bug #36798: --- php-5.2.6/ext/pdo/pdo_sql_parser.re 2007-12-31 01:17:40.000000000 -0600 +++ php-5.2.6.fixed/ext/pdo/pdo_sql_parser.re 2008-09-08 11:06:39.000000000 -0500 @@ -55,8 +55,8 @@ */ /*!re2c - (["] ([^"])* ["]) { RET(PDO_PARSER_TEXT); } - (['] ([^'])* [']) { RET(PDO_PARSER_TEXT); } + (["](([\\]ANYNOEOF)|ANYNOEOF\["\\])*["]) { RET(PDO_PARSER_TEXT); } + (['](([\\]ANYNOEOF)|ANYNOEOF\['\\])*[']) { RET(PDO_PARSER_TEXT); } MULTICHAR{2,} { RET(PDO_PARSER_TEXT); } BINDCHR { RET(PDO_PARSER_BIND); } QUESTION { RET(PDO_PARSER_BIND_POS); } --- php-5.2.6/ext/pdo/pdo_sql_parser.c 2008-04-30 13:37:40.000000000 -0500 +++ php-5.2.6.fixed/ext/pdo/pdo_sql_parser.c 2008-09-08 11:06:43.000000000 -0500 @@ -1,4 +1,5 @@ -/* Generated by re2c 0.11.0 on Mon Nov 26 16:10:28 2007 */ +/* Generated by re2c 0.13.5 on Mon Sep 8 11:06:43 2008 */ +#line 1 "ext/pdo/pdo_sql_parser.re" /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -17,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: pdo_sql_parser.c,v 1.35.2.6.2.15 2007/12/31 07:20:09 sebastian Exp $ */ +/* $Id: pdo_sql_parser.re,v 1.28.2.4.2.12 2007/12/31 07:17:40 sebastian Exp $ */ #include "php.h" #include "php_pdo_driver.h" @@ -46,15 +47,17 @@ char *cursor = s->cur; s->tok = cursor; + #line 55 "ext/pdo/pdo_sql_parser.re" +#line 55 "ext/pdo/pdo_sql_parser.c" { YYCTYPE yych; - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; - switch(yych) { + switch (yych) { case 0x00: goto yy11; case '"': goto yy2; case '\'': goto yy4; @@ -63,16 +66,19 @@ default: goto yy8; } yy2: - yych = *++YYCURSOR; - goto yy24; + yych = *(YYMARKER = ++YYCURSOR); + if (yych >= 0x01) goto yy26; yy3: +#line 63 "ext/pdo/pdo_sql_parser.re" { SKIP_ONE(PDO_PARSER_TEXT); } +#line 75 "ext/pdo/pdo_sql_parser.c" yy4: - yych = *++YYCURSOR; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x00) goto yy3; goto yy20; yy5: yych = *++YYCURSOR; - switch(yych) { + switch (yych) { case '0': case '1': case '2': @@ -142,18 +148,20 @@ } yy6: ++YYCURSOR; - switch((yych = *YYCURSOR)) { + switch ((yych = *YYCURSOR)) { case ':': case '?': goto yy13; default: goto yy7; } yy7: +#line 62 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND_POS); } +#line 160 "ext/pdo/pdo_sql_parser.c" yy8: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - switch(yych) { + switch (yych) { case 0x00: case '"': case '\'': @@ -162,26 +170,32 @@ default: goto yy8; } yy10: +#line 64 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } +#line 176 "ext/pdo/pdo_sql_parser.c" yy11: ++YYCURSOR; +#line 65 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_EOI); } +#line 181 "ext/pdo/pdo_sql_parser.c" yy13: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - switch(yych) { + switch (yych) { case ':': case '?': goto yy13; default: goto yy15; } yy15: +#line 60 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } +#line 194 "ext/pdo/pdo_sql_parser.c" yy16: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - switch(yych) { + switch (yych) { case '0': case '1': case '2': @@ -248,32 +262,58 @@ default: goto yy18; } yy18: +#line 61 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND); } +#line 268 "ext/pdo/pdo_sql_parser.c" yy19: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; yy20: - switch(yych) { - case '\'': goto yy21; + switch (yych) { + case 0x00: goto yy21; + case '\'': goto yy23; + case '\\': goto yy22; default: goto yy19; } yy21: + YYCURSOR = YYMARKER; + goto yy3; +yy22: ++YYCURSOR; - { RET(PDO_PARSER_TEXT); } + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy21; + goto yy19; yy23: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); +#line 59 "ext/pdo/pdo_sql_parser.re" + { RET(PDO_PARSER_TEXT); } +#line 293 "ext/pdo/pdo_sql_parser.c" +yy25: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; -yy24: - switch(yych) { - case '"': goto yy25; - default: goto yy23; +yy26: + switch (yych) { + case 0x00: goto yy21; + case '"': goto yy28; + case '\\': goto yy27; + default: goto yy25; } -yy25: +yy27: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy21; + goto yy25; +yy28: ++YYCURSOR; +#line 58 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } +#line 315 "ext/pdo/pdo_sql_parser.c" } +#line 66 "ext/pdo/pdo_sql_parser.re" } Previous Comments: ------------------------------------------------------------------------ [2008-09-09 14:38:35] om at viazenetti dot de Nice, after almost seven months, this bug still exists and no one cares about it? ------------------------------------------------------------------------ [2008-09-05 17:59:42] tsteiner at nerdclub dot net This bug is a direct result of the fix for Bug #36798. The patch for that bug removed code in the parser that would ignore an escaped quote when inside of quotes (ie: "foo\"bar" or 'foo\'bar'). This causes the parser to think it has found the end of quoted text, when it has not. Because of this, ? characters after an escaped quote are treated as placeholders. Additionally, I have found it causes the parser to parse beyond the end of the query and into unknown memory contents. It looks like Bug #36798 needs to be reopened! ------------------------------------------------------------------------ [2008-02-26 11:11:13] om at viazenetti dot de Description: ------------ If a question mark and an escaped singel quote appear in a where statement as value, the PDO method prepare tries to bind a value to the question mark. Because no values are passed, pdo throws an exception (Only tested with where statements): PDOStatement::execute() [function.PDOStatement-execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in Reproduce code: --------------- <?php $db = new PDO('mysql:host=localhost;dbname=DATABASE', 'USER', 'PASSWORD'); $sth = $db->prepare("SELECT * FROM `TABLE` WHERE (login = '?\'')"); $sth->execute(); var_dump($sth->fetch()); Expected result: ---------------- Array or false Actual result: -------------- Exception: PDOStatement::execute() [function.PDOStatement-execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=44251&edit=1