summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/pdo/pdo_sql_parser.c82
-rw-r--r--ext/pdo/pdo_sql_parser.re8
-rw-r--r--ext/pdo_mysql/tests/bug41125.phpt162
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
+--------