From fe0e60a20de530d52a5a5335af898752681fbef7 Mon Sep 17 00:00:00 2001 From: Robin Gloster Date: Fri, 17 Oct 2014 15:20:32 +0200 Subject: [PATCH 1/2] loosen regex to allow nested function calls in sql this essentially is a recursive regex to ensure balanced parantheses --- library/Zend/Db/Select.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/Zend/Db/Select.php b/library/Zend/Db/Select.php index 51f6ddf645..efb738a508 100644 --- a/library/Zend/Db/Select.php +++ b/library/Zend/Db/Select.php @@ -509,7 +509,7 @@ public function group($spec) } foreach ($spec as $val) { - if (preg_match('/^[\w]*\([^\)]*\)$/', (string) $val)) { + if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $val)) { $val = new Zend_Db_Expr($val); } $this->_parts[self::GROUP][] = $val; @@ -601,7 +601,7 @@ public function order($spec) $val = trim($matches[1]); $direction = $matches[2]; } - if (preg_match('/^[\w]*\([^\)]*\)$/', $val)) { + if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $val)) { $val = new Zend_Db_Expr($val); } $this->_parts[self::ORDER][] = array($val, $direction); @@ -943,7 +943,7 @@ protected function _tableCols($correlationName, $cols, $afterCorrelationName = n $alias = $m[2]; } // Check for columns that look like functions and convert to Zend_Db_Expr - if (preg_match('/^[\w]*\([^\)]*\)$/', $col)) { + if (preg_match('/^([\w]*\(([^\)]|(?1))*\))$/', (string) $col)) { $col = new Zend_Db_Expr($col); } elseif (preg_match('/(.+)\.(.+)/', $col, $m)) { $currentCorrelationName = $m[1]; From c630cda3bc7ccf614cc1f06ab7e5e543c7ad6633 Mon Sep 17 00:00:00 2001 From: Robin Gloster Date: Mon, 1 Dec 2014 12:29:12 +0100 Subject: [PATCH 2/2] add unittest for nested functions in columns in Zend_Db_Select --- tests/Zend/Db/Select/StaticTest.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/Zend/Db/Select/StaticTest.php b/tests/Zend/Db/Select/StaticTest.php index 8feffd198c..482c77efed 100644 --- a/tests/Zend/Db/Select/StaticTest.php +++ b/tests/Zend/Db/Select/StaticTest.php @@ -854,6 +854,26 @@ public function testSqlInjectionInColumn() $this->assertEquals('SELECT "p"."MD5(1); drop table products; -- )" FROM "products" AS "p"', $select->assemble()); } + public function testIfInColumn() + { + $select = $this->_db->select(); + $select->from('table1', '*'); + $select->join(array('table2'), + 'table1.id = table2.id', + array('bar' => 'IF(table2.id IS NOT NULL, 1, 0)')); + $this->assertEquals("SELECT \"table1\".*, IF(table2.id IS NOT NULL, 1, 0) AS \"bar\" FROM \"table1\"\n INNER JOIN \"table2\" ON table1.id = table2.id", $select->assemble()); + } + + public function testNestedIfInColumn() + { + $select = $this->_db->select(); + $select->from('table1', '*'); + $select->join(array('table2'), + 'table1.id = table2.id', + array('bar' => 'IF(table2.id IS NOT NULL, IF(table2.id2 IS NOT NULL, 1, 2), 0)')); + $this->assertEquals("SELECT \"table1\".*, IF(table2.id IS NOT NULL, IF(table2.id2 IS NOT NULL, 1, 2), 0) AS \"bar\" FROM \"table1\"\n INNER JOIN \"table2\" ON table1.id = table2.id", $select->assemble()); + } + /** * @group ZF-378 */