diff --git a/ext/pdo/pdo_sql_parser.c b/ext/pdo/pdo_sql_parser.c index 5966760fc37..c4abdb11184 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 16:10:00 2007 */ +/* Generated by re2c 0.13.5 on Fri Oct 10 09:03:17 2008 */ #line 1 "ext/pdo/pdo_sql_parser.re" /* +----------------------------------------------------------------------+ @@ -47,7 +47,7 @@ static int scan(Scanner *s) char *cursor = s->cur; s->tok = cursor; - #line 54 "ext/pdo/pdo_sql_parser.re" + #line 55 "ext/pdo/pdo_sql_parser.re" @@ -55,9 +55,9 @@ static int scan(Scanner *s) { YYCTYPE yych; - if((YYLIMIT - YYCURSOR) < 3) YYFILL(3); + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; - switch(yych) { + switch (yych) { case 0x00: goto yy11; case '"': goto yy2; case '\'': goto yy4; @@ -66,34 +66,19 @@ static int scan(Scanner *s) default: goto yy8; } yy2: - yych = *++YYCURSOR; - switch(yych) { - case '"': goto yy26; - case '\'': - case ':': - case '?': goto yy28; - default: goto yy30; - } + yych = *(YYMARKER = ++YYCURSOR); + if (yych >= 0x01) goto yy26; yy3: -#line 62 "ext/pdo/pdo_sql_parser.re" +#line 63 "ext/pdo/pdo_sql_parser.re" { SKIP_ONE(PDO_PARSER_TEXT); } -#line 81 "ext/pdo/pdo_sql_parser.c" +#line 75 "ext/pdo/pdo_sql_parser.c" yy4: - yych = *++YYCURSOR; - switch(yych) { - case '"': - case ':': - case '?': goto yy19; - case '\'': goto yy21; - default: goto yy23; - } + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x00) goto yy3; + goto yy20; yy5: yych = *++YYCURSOR; - switch(yych) { - case '"': - case '\'': - case ':': - case '?': goto yy13; + switch (yych) { case '0': case '1': case '2': @@ -157,26 +142,26 @@ yy5: case 'x': case 'y': case 'z': goto yy16; + case ':': + case '?': goto yy13; default: goto yy3; } yy6: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case '"': - case '\'': + switch ((yych = *YYCURSOR)) { case ':': case '?': goto yy13; default: goto yy7; } yy7: -#line 61 "ext/pdo/pdo_sql_parser.re" +#line 62 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND_POS); } -#line 175 "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 '\'': @@ -185,34 +170,32 @@ yy8: default: goto yy8; } yy10: -#line 63 "ext/pdo/pdo_sql_parser.re" +#line 64 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 191 "ext/pdo/pdo_sql_parser.c" +#line 176 "ext/pdo/pdo_sql_parser.c" yy11: ++YYCURSOR; -#line 64 "ext/pdo/pdo_sql_parser.re" +#line 65 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_EOI); } -#line 196 "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) { - case '"': - case '\'': + switch (yych) { case ':': case '?': goto yy13; default: goto yy15; } yy15: -#line 59 "ext/pdo/pdo_sql_parser.re" +#line 60 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_TEXT); } -#line 211 "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': @@ -279,80 +262,58 @@ yy16: default: goto yy18; } yy18: -#line 60 "ext/pdo/pdo_sql_parser.re" +#line 61 "ext/pdo/pdo_sql_parser.re" { RET(PDO_PARSER_BIND); } -#line 285 "ext/pdo/pdo_sql_parser.c" +#line 268 "ext/pdo/pdo_sql_parser.c" yy19: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - switch(yych) { - case '"': - case ':': - case '?': goto yy19; - case '\'': goto yy21; - default: goto yy23; +yy20: + switch (yych) { + case 0x00: goto yy21; + case '\'': goto yy23; + case '\\': goto yy22; + default: goto yy19; } yy21: - ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case '"': - case '\'': - case ':': - case '?': goto yy13; - default: goto yy22; - } + YYCURSOR = YYMARKER; + goto yy3; yy22: -#line 58 "ext/pdo/pdo_sql_parser.re" - { RET(PDO_PARSER_TEXT); } -#line 308 "ext/pdo/pdo_sql_parser.c" + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy21; + goto yy19; yy23: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych) { - case '\'': goto yy25; - default: goto yy23; - } +#line 59 "ext/pdo/pdo_sql_parser.re" + { RET(PDO_PARSER_TEXT); } +#line 293 "ext/pdo/pdo_sql_parser.c" yy25: - yych = *++YYCURSOR; - goto yy22; -yy26: ++YYCURSOR; - switch((yych = *YYCURSOR)) { - case '"': - case '\'': - case ':': - case '?': goto yy13; - default: goto yy27; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy26: + switch (yych) { + case 0x00: goto yy21; + case '"': goto yy28; + case '\\': goto yy27; + default: goto yy25; } yy27: -#line 57 "ext/pdo/pdo_sql_parser.re" - { RET(PDO_PARSER_TEXT); } -#line 332 "ext/pdo/pdo_sql_parser.c" + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 0x00) goto yy21; + goto yy25; yy28: - if((YYLIMIT - YYCURSOR) < 2) YYFILL(2); - yych = *YYCURSOR; - switch(yych) { - case '"': goto yy26; - case '\'': - case ':': - case '?': goto yy28; - default: goto yy30; - } -yy30: ++YYCURSOR; - if(YYLIMIT == YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - switch(yych) { - case '"': goto yy32; - default: goto yy30; - } -yy32: - ++YYCURSOR; - yych = *YYCURSOR; - goto yy27; +#line 58 "ext/pdo/pdo_sql_parser.re" + { RET(PDO_PARSER_TEXT); } +#line 315 "ext/pdo/pdo_sql_parser.c" } -#line 65 "ext/pdo/pdo_sql_parser.re" +#line 66 "ext/pdo/pdo_sql_parser.re" } @@ -496,7 +457,7 @@ safe: size_t len; char *buf = NULL; - len = php_stream_copy_to_mem(stm, &buf, PHP_STREAM_COPY_ALL, 0); + len = php_stream_copy_to_mem(stm, (void *)&buf, PHP_STREAM_COPY_ALL, 0); if (!stmt->dbh->methods->quoter(stmt->dbh, buf, len, &plc->quoted, &plc->qlen, param->param_type TSRMLS_CC)) { /* bork */ diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index 815c3d400c3..299b1d0d05a 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -49,14 +49,15 @@ static int scan(Scanner *s) BINDCHR = [:][a-zA-Z0-9_]+; QUESTION = [?]; SPECIALS = [:?"']; - EOF = [\000]; + MULTICHAR = [:?]; + EOF = [\000]; ANYNOEOF = [\001-\377]; */ /*!re2c - (["] ([^"])* ["]) { RET(PDO_PARSER_TEXT); } - (['] ([^'])* [']) { RET(PDO_PARSER_TEXT); } - SPECIALS{2,} { 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); } SPECIALS { SKIP_ONE(PDO_PARSER_TEXT); } diff --git a/ext/pdo_mysql/tests/bug41125.phpt b/ext/pdo_mysql/tests/bug41125.phpt new file mode 100644 index 00000000000..5889a4d2910 --- /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-- + +--FILE-- +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 +--------