]> granicus.if.org Git - php/commitdiff
- Fixed bug #44251 (Question mark and an escaped singel quote lead to an exception)
authorFelipe Pena <felipe@php.net>
Fri, 10 Oct 2008 12:08:07 +0000 (12:08 +0000)
committerFelipe Pena <felipe@php.net>
Fri, 10 Oct 2008 12:08:07 +0000 (12:08 +0000)
- Fixed bug #41125 (PDO mysql + quote() + prepare() can result in seg fault)
  Patch by: tsteiner at nerdclub dot net

ext/pdo/pdo_sql_parser.c
ext/pdo/pdo_sql_parser.re
ext/pdo_mysql/tests/bug41125.phpt [new file with mode: 0644]

index 5966760fc377476bd75a4368d3f92dce564fa6aa..c4abdb11184e7cd4fe9cd74c32e3b689f082efcd 100644 (file)
@@ -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"
-yy23:
        ++YYCURSOR;
-       if(YYLIMIT == YYCURSOR) YYFILL(1);
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       switch(yych) {
-       case '\'':      goto yy25;
-       default:        goto yy23;
-       }
-yy25:
-       yych = *++YYCURSOR;
-       goto yy22;
-yy26:
+       if (yych <= 0x00) goto yy21;
+       goto yy19;
+yy23:
        ++YYCURSOR;
-       switch((yych = *YYCURSOR)) {
-       case '"':
-       case '\'':
-       case ':':
-       case '?':       goto yy13;
-       default:        goto yy27;
-       }
-yy27:
-#line 57 "ext/pdo/pdo_sql_parser.re"
+#line 59 "ext/pdo/pdo_sql_parser.re"
        { RET(PDO_PARSER_TEXT); }
-#line 332 "ext/pdo/pdo_sql_parser.c"
-yy28:
-       if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
-       yych = *YYCURSOR;
-       switch(yych) {
-       case '"':       goto yy26;
-       case '\'':
-       case ':':
-       case '?':       goto yy28;
-       default:        goto yy30;
-       }
-yy30:
+#line 293 "ext/pdo/pdo_sql_parser.c"
+yy25:
        ++YYCURSOR;
-       if(YYLIMIT == YYCURSOR) YYFILL(1);
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       switch(yych) {
-       case '"':       goto yy32;
-       default:        goto yy30;
+yy26:
+       switch (yych) {
+       case 0x00:      goto yy21;
+       case '"':       goto yy28;
+       case '\\':      goto yy27;
+       default:        goto yy25;
        }
-yy32:
+yy27:
        ++YYCURSOR;
+       if (YYLIMIT <= YYCURSOR) YYFILL(1);
        yych = *YYCURSOR;
-       goto yy27;
+       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 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 */
index 815c3d400c3cb659a98c4c3f79e4bd15d7968a41..299b1d0d05a91fd65d457d4c4ffeeacb2d4ba138 100644 (file)
@@ -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 (file)
index 0000000..5889a4d
--- /dev/null
@@ -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
+--------