Parcourir la source

fixes ZF-7911, not the segfaults, but it should no longer be incomplete and tests are added, so that further research is easier

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@24788 44c647ce-9c0f-0410-b52a-842ac1e357ba
mcleod@spaceweb.nl il y a 13 ans
Parent
commit
98b6947fa1
2 fichiers modifiés avec 134 ajouts et 19 suppressions
  1. 19 19
      library/Zend/Db/Statement.php
  2. 115 0
      tests/Zend/Db/Statement/MysqliTest.php

+ 19 - 19
library/Zend/Db/Statement.php

@@ -176,37 +176,37 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
      */
     protected function _stripQuoted($sql)
     {
-        // get the character for delimited id quotes,
-        // this is usually " but in MySQL is `
-        $d = $this->_adapter->quoteIdentifier('a');
-        $d = $d[0];
-
-        // get the value used as an escaped delimited id quote,
-        // e.g. \" or "" or \`
-        $de = $this->_adapter->quoteIdentifier($d);
-        $de = substr($de, 1, 2);
-        $de = str_replace('\\', '\\\\', $de);
 
         // get the character for value quoting
         // this should be '
         $q = $this->_adapter->quote('a');
-        $q = $q[0];
-
+        $q = $q[0];        
         // get the value used as an escaped quote,
         // e.g. \' or ''
         $qe = $this->_adapter->quote($q);
         $qe = substr($qe, 1, 2);
-        $qe = str_replace('\\', '\\\\', $qe);
-
-        // get a version of the SQL statement with all quoted
-        // values and delimited identifiers stripped out
-        // remove "foo\"bar"
-        $sql = preg_replace("/$q($qe|\\\\{2}|[^$q])*$q/", '', $sql);
+        $qe = preg_quote($qe);
         // remove 'foo\'bar'
         if (!empty($q)) {
-            $sql = preg_replace("/$q($qe|[^$q])*$q/", '', $sql);
+            $sql = preg_replace("/$q($qe|[^$q])*$q/Us", '', $sql);
         }
+        
+        // get a version of the SQL statement with all quoted
+        // values and delimited identifiers stripped out
+        // remove "foo\"bar"
+        $sql = preg_replace("/\"(\\\\\"|[^\"])*\"/Us", '', $sql);
 
+        // get the character for delimited id quotes,
+        // this is usually " but in MySQL is `
+        $d = $this->_adapter->quoteIdentifier('a');
+        $d = $d[0];
+        // get the value used as an escaped delimited id quote,
+        // e.g. \" or "" or \`
+        $de = $this->_adapter->quoteIdentifier($d);
+        $de = substr($de, 1, 2);
+        $de = preg_quote($de);
+        // Note: $de and $d where never used..., now they are:
+        $sql = preg_replace("/$d($de|\\\\{2}|[^$d])*$d/Us", '', $sql);
         return $sql;
     }
 

+ 115 - 0
tests/Zend/Db/Statement/MysqliTest.php

@@ -21,7 +21,18 @@
  */
 
 require_once 'Zend/Db/Statement/TestCommon.php';
+require_once 'Zend/Db/Statement/Mysqli.php';
 
+/**
+ * Wrapper class for test protected function _stripQuoted
+ */
+class Zend_Db_Statement_Mysqli_Test_Class extends Zend_Db_Statement_Mysqli
+{
+    public function stripQuoted($sql)
+    {
+        return $this->_stripQuoted($sql);
+    }
+}
 
 /**
  * @category   Zend
@@ -34,7 +45,111 @@ require_once 'Zend/Db/Statement/TestCommon.php';
  */
 class Zend_Db_Statement_MysqliTest extends Zend_Db_Statement_TestCommon
 {
+    protected $_Zend_Db_Statement_Mysqli_Test_Class = null;
+    /**
+     * @group ZF-7911
+     */
+    public function testStripQuoted()
+    {
+        $this->_Zend_Db_Statement_Mysqli_Test_Class = new Zend_Db_Statement_Mysqli_Test_Class($this->_db, "SELECT 1");
+        
+        $input = <<<INPUT
+in: [SELECT * FROM `strange`table1`]
+out: [SELECT * FROM table1`]
+    
+in: [SELECT * FROM `strange``table2`]
+out: [SELECT * FROM ]
+    
+in: [SELECT * FROM `strange```table3`]
+out: [SELECT * FROM table3`]
+    
+in: [SELECT * FROM `strange\`table4`]
+out: [SELECT * FROM table4`]
+    
+in: [SELECT * FROM `strange\``table5`]
+out: [SELECT * FROM ]
+    
+in: [SELECT * FROM `strange\```table6`]
+out: [SELECT * FROM table6`]
+    
+in: [SELECT 'value7' AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT 'strange:value8' AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT 'strange'value9' AS identifier]
+out: [SELECT value9' AS identifier]
+    
+in: [SELECT 'strange''value10' AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT 'strange'''value11' AS identifier]
+out: [SELECT value11' AS identifier]
+    
+in: [SELECT 'strange\'value12' AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT 'strange\''value13' AS identifier]
+out: [SELECT value13' AS identifier]
+    
+in: [SELECT 'strange'''value14' AS identifier]
+out: [SELECT value14' AS identifier]
+    
+in: [SELECT "value15" AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT "strange:value16" AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT "strange"value17" AS identifier]
+out: [SELECT value17" AS identifier]
+    
+in: [SELECT "strange""value18" AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT "strange"""value19" AS identifier]
+out: [SELECT value19" AS identifier]
+    
+in: [SELECT "strange\"value20" AS identifier]
+out: [SELECT  AS identifier]
+    
+in: [SELECT "strange\""value21" AS identifier]
+out: [SELECT value21" AS identifier]
+    
+in: [SELECT "strange"""value22" AS identifier]
+out: [SELECT value22" AS identifier]
+        
+in: [SELECT 'strange\'''value23' AS identifier]
+out: [SELECT  AS identifier]
+        
+in: [SELECT '?`' `x`, col `y` FROM t WHERE u = ?;]
+out: [SELECT  , col  FROM t WHERE u = ?;]
 
+in: [SELECT "?`" `x`, col `y` FROM t WHERE u = ?;]
+out: [SELECT  , col  FROM t WHERE u = ?;]
+
+in: [INSERT INTO `pcre` (`test`) VALUES ('In MySQL, the backtick (`) is used to quoted identifiers, and here is another backtick: ` ...ooops');]
+out: [INSERT INTO  () VALUES ();]
+INPUT;
+        // parse the input
+        $inputOutputLines = explode('in:', $input);
+        $count = 0;
+    
+        foreach ($inputOutputLines as $ioLine) {
+            if (!trim($ioLine)) {
+                continue;
+            }
+    
+            $count++;
+            $io = explode('out:', $ioLine);
+            $in = str_replace(array('[', ']'),'', trim($io[0]));
+            $out = str_replace(array('[', ']'),'', trim($io[1]));
+            $actual = $this->_Zend_Db_Statement_Mysqli_Test_Class->stripQuoted($in);
+            $this->assertSame($out, $actual, $count . ' - unexpected output');
+        }
+    }
+    
     public function testStatementRowCount()
     {
         $products = $this->_db->quoteIdentifier('zfproducts');