diff options
-rw-r--r-- | ext/pdo/pdo_sql_parser.c | 82 | ||||
-rw-r--r-- | ext/pdo/pdo_sql_parser.re | 8 | ||||
-rw-r--r-- | ext/pdo_mysql/tests/bug41125.phpt | 162 |
3 files changed, 217 insertions, 35 deletions
diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 2b97de9c53..142242f60a 100644 --- a/ext/pdo/pdo_sql_parser.c +++ b/ext/pdo/pdo_sql_parser.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.11.0 on Mon Nov 26 15:18:37 2007 */ +/* Generated by re2c 0.13.5 on Fri Oct 10 08:59:42 2008 */ #line 1 "ext/pdo/pdo_sql_parser.re" /* +----------------------------------------------------------------------+ @@ -55,9 +55,9 @@ static int scan(Scanner *s) { 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; @@ -66,18 +66,19 @@ static int scan(Scanner *s) 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': @@ -147,7 +148,7 @@ yy5: } yy6: ++YYCURSOR; - switch((yych = *YYCURSOR)) { + switch ((yych = *YYCURSOR)) { case ':': case '?': goto yy13; default: goto yy7; @@ -155,12 +156,12 @@ yy6: yy7: #line 62 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND_POS); } -#line 159 "ext/pdo/pdo_sql_parser.c" +#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 '\'': @@ -171,17 +172,17 @@ yy8: yy10: #line 64 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 175 "ext/pdo/pdo_sql_parser.c" +#line 176 "ext/pdo/pdo_sql_parser.c" yy11: ++YYCURSOR; #line 65 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_EOI); } -#line 180 "ext/pdo/pdo_sql_parser.c" +#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; @@ -189,12 +190,12 @@ yy13: yy15: #line 60 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 193 "ext/pdo/pdo_sql_parser.c" +#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': @@ -263,35 +264,54 @@ yy16: yy18: #line 61 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND); } -#line 267 "ext/pdo/pdo_sql_parser.c" +#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; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy21; + goto yy19; +yy23: ++YYCURSOR; #line 59 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 281 "ext/pdo/pdo_sql_parser.c" -yy23: +#line 293 "ext/pdo/pdo_sql_parser.c" +yy25: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); + 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 295 "ext/pdo/pdo_sql_parser.c" +#line 315 "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 a2a8f34395..88fbb6055f 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -50,15 +50,15 @@ static int scan(Scanner *s) QUESTION = [?]; SPECIALS = [:?"']; MULTICHAR = [:?]; - EOF = [\000]; + EOF = [\000]; ANYNOEOF = [\001-\377]; */ /*!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); } + BINDCHR { RET(PDO_PARSER_BIND); } QUESTION { RET(PDO_PARSER_BIND_POS); } SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); } (ANYNOEOF\SPECIALS)+ { RET(PDO_PARSER_TEXT); } diff --git a/ext/pdo_mysql/tests/bug41125.phpt b/ext/pdo_mysql/tests/bug41125.phpt new file mode 100644 index 0000000000..5889a4d291 --- /dev/null +++ b/ext/pdo_mysql/tests/bug41125.phpt @@ -0,0 +1,162 @@ +--TEST-- +Bug #41125 (PDO mysql + quote() + prepare() can result in seg fault) +--SKIPIF-- +<?php +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); +MySQLPDOTest::skip(); + +?> +--FILE-- +<?php + +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + +$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt'); + +$search = "o'"; +$sql = "SELECT 1 FROM DUAL WHERE 'o''riley' LIKE " . $db->quote('%' . $search . '%'); +$stmt = $db->prepare($sql); +$stmt->execute(); +print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; +print implode(' - ', $stmt->errorinfo()) ."\n"; + +print "-------------------------------------------------------\n"; + +$queries = array( + "SELECT 1 FROM DUAL WHERE 1 = '?\'\''", + "SELECT 'a\\'0' FROM DUAL WHERE 1 = ?", + "SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND ?", + "SELECT 'foo?bar', '', '''' FROM DUAL WHERE ?" +); + +foreach ($queries as $k => $query) { + $stmt = $db->prepare($query); + $stmt->execute(array(1)); + printf("[%d] Query: [[%s]]\n", $k + 1, $query); + print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; + print implode(' - ', $stmt->errorinfo()) ."\n"; + print "--------\n"; +} + +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$sql = "SELECT upper(:id) FROM DUAL WHERE '1'"; +$stmt = $db->prepare($sql); + +$id = 'o\'\0'; +$stmt->bindParam(':id', $id); +$stmt->execute(); +printf("Query: [[%s]]\n", $sql); +print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; +print implode(' - ', $stmt->errorinfo()) ."\n"; + +print "-------------------------------------------------------\n"; + +$queries = array( + "SELECT 1, 'foo' FROM DUAL WHERE 1 = :id AND '\\0' IS NULL AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '' AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '\'\'' = '''' AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '\'' = '''' AND 2 <> :id", + "SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND 1", + "SELECT 'a''', '\'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND 1", + "SELECT UPPER(:id) FROM DUAL WHERE '1'", + "SELECT 1 FROM DUAL WHERE '\''", + "SELECT 1 FROM DUAL WHERE :id AND '\\0' OR :id", + "SELECT 1 FROM DUAL WHERE 'a\\f\\n\\0' AND 1 >= :id", + "SELECT 1 FROM DUAL WHERE '\'' = ''''", + "SELECT '\\n' '1 FROM DUAL WHERE '''' and :id'", + "SELECT 1 'FROM DUAL WHERE :id AND '''' = '''' OR 1 = 1 AND ':id", +); + +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$id = 1; + +foreach ($queries as $k => $query) { + $stmt = $db->prepare($query); + $stmt->bindParam(':id', $id); + $stmt->execute(); + + printf("[%d] Query: [[%s]]\n", $k + 1, $query); + print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; + print implode(' - ', $stmt->errorinfo()) ."\n"; + print "--------\n"; +} + +?> +--EXPECT-- +1 +00000 +------------------------------------------------------- +[1] Query: [[SELECT 1 FROM DUAL WHERE 1 = '?\'\'']] + +00000 +-------- +[2] Query: [[SELECT 'a\'0' FROM DUAL WHERE 1 = ?]] +a'0 +00000 +-------- +[3] Query: [[SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\'' AND ?]] +a - b' +00000 +-------- +[4] Query: [[SELECT 'foo?bar', '', '''' FROM DUAL WHERE ?]] +foo?bar - - ' +00000 +-------- +Query: [[SELECT upper(:id) FROM DUAL WHERE '1']] +O'\0 +00000 +------------------------------------------------------- +[1] Query: [[SELECT 1, 'foo' FROM DUAL WHERE 1 = :id AND '\0' IS NULL AND 2 <> :id]] + +00000 +-------- +[2] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '' AND 2 <> :id]] + +00000 +-------- +[3] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '\'\'' = '''' AND 2 <> :id]] + +00000 +-------- +[4] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '\'' = '''' AND 2 <> :id]] +1 +00000 +-------- +[5] Query: [[SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\'' AND 1]] +a - b' +00000 +-------- +[6] Query: [[SELECT 'a''', '\'b\'' FROM DUAL WHERE '''' LIKE '\'' AND 1]] +a' - 'b' +00000 +-------- +[7] Query: [[SELECT UPPER(:id) FROM DUAL WHERE '1']] +1 +00000 +-------- +[8] Query: [[SELECT 1 FROM DUAL WHERE '\'']] + +00000 +-------- +[9] Query: [[SELECT 1 FROM DUAL WHERE :id AND '\0' OR :id]] +1 +00000 +-------- +[10] Query: [[SELECT 1 FROM DUAL WHERE 'a\f\n\0' AND 1 >= :id]] + +00000 +-------- +[11] Query: [[SELECT 1 FROM DUAL WHERE '\'' = '''']] +1 +00000 +-------- +[12] Query: [[SELECT '\n' '1 FROM DUAL WHERE '''' and :id']] + +1 FROM DUAL WHERE '' and :id +00000 +-------- +[13] Query: [[SELECT 1 'FROM DUAL WHERE :id AND '''' = '''' OR 1 = 1 AND ':id]] +1 +00000 +-------- |