diff options
-rw-r--r-- | system/database/DB_driver.php | 6 | ||||
-rw-r--r-- | system/database/DB_query_builder.php | 10 | ||||
-rw-r--r-- | tests/codeigniter/database/query_builder/join_test.php | 20 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 1 |
4 files changed, 29 insertions, 8 deletions
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index d5367b4d2..1060ecc6c 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -970,7 +970,7 @@ abstract class CI_DB_driver { */ public function escape_identifiers($item) { - if ($this->_escape_char === '') + if ($this->_escape_char === '' OR empty($item)) { return $item; } @@ -983,8 +983,8 @@ abstract class CI_DB_driver { return $item; } - // Avoid breaking functions inside queries - elseif (strpos($item, '(') !== FALSE) + // Avoid breaking functions and literal values inside queries + elseif (ctype_digit($item) OR $item[0] === "'" OR strpos($item, '(') !== FALSE) { return $item; } diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 79e67e0c0..479b7f24a 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -350,18 +350,18 @@ abstract class CI_DB_query_builder extends CI_DB_driver { is_bool($escape) OR $escape = $this->_protect_identifiers; // Split multiple conditions - if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) + if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_OFFSET_CAPTURE)) { $newcond = ''; $m[0][] = array('', strlen($cond)); for ($i = 0, $c = count($m[0]), $s = 0; $i < $c; - $s += $m[0][$i][1] + strlen($m[0][$i][0]), $i++) + $s = $m[0][$i][1] + strlen($m[0][$i][0]), $i++) { - $temp = substr($cond, $s, $m[0][$i][1]); + $temp = substr($cond, $s, ($m[0][$i][1] - $s)); - $newcond .= preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $temp, $match) + $newcond .= preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $temp, $match) ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]) : $temp; @@ -371,7 +371,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $cond = ' ON '.$newcond; } // Split apart the condition and protect the identifiers - elseif ($escape === TRUE && preg_match('/([\[\w\.-]+)([\W\s]+)(.+)/i', $cond, $match)) + elseif ($escape === TRUE && preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $cond, $match)) { $cond = ' ON '.$this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]); } diff --git a/tests/codeigniter/database/query_builder/join_test.php b/tests/codeigniter/database/query_builder/join_test.php index b8cf2a822..6d5fc64af 100644 --- a/tests/codeigniter/database/query_builder/join_test.php +++ b/tests/codeigniter/database/query_builder/join_test.php @@ -35,4 +35,24 @@ class Join_test extends CI_TestCase { $this->assertEquals('Developer', $job_user[0]['job_name']); } + // ------------------------------------------------------------------------ + + public function test_join_escape_multiple_conditions() + { + // We just need a valid query produced, not one that makes sense + $fields = array($this->db->protect_identifiers('table1.field1'), $this->db->protect_identifiers('table2.field2')); + + $expected = 'SELECT '.implode(', ', $fields) + ."\nFROM ".$this->db->escape_identifiers('table1') + ."\nLEFT JOIN ".$this->db->escape_identifiers('table2').' ON '.implode(' = ', $fields) + .' AND '.$fields[0]." = 'foo' AND ".$fields[1].' = 0'; + + $result = $this->db->select('table1.field1, table2.field2') + ->from('table1') + ->join('table2', "table1.field1 = table2.field2 AND table1.field1 = 'foo' AND table2.field2 = 0", 'LEFT') + ->get_compiled_select(); + + $this->assertEquals($sql, $result); + } + }
\ No newline at end of file diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 716e08f63..75229f91f 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -307,6 +307,7 @@ Bug fixes for 3.0 - Fixed a bug (#427) - :doc:`Form Validation Library <libraries/form_validation>` method ``strip_image_tags()`` was an alias to a non-existent method. - Fixed a bug (#1545) - :doc:`Query Builder <database/query_builder>` method ``limit()`` wasn't executed properly under Oracle. - Fixed a bug (#1551) - :doc:`Date Helper <helpers/date_helper>` function ``standard_date()`` didn't properly format *W3C* and *ATOM* standard dates. +- Fixed a bug in :doc:`Query Builder <database/query_builder>` method join() where literal values were escaped as if they were fields. Version 2.1.2 ============= |