Welcome Guest, Not a member yet? Register   Sign In
Query binding bug
#1

[eluser]miau[/eluser]
Hi, I found a bug in query binding.
The following code:
Code:
$test = "test\\";    
$this->db->query("insert into test(name) values (?)", array($test));
will not work because during binding one of backslashes disappears.
It happens in compile_binds() (DB_driver.php) in this line:
Code:
$sql = preg_replace("#".preg_quote($this->bind_marker, '#')."#", str_replace('$', '\$', $val), $sql, 1);
($val is after escaping)

My solution is to replace the code from above with this:
Code:
$pos = strpos($sql, $this->bind_marker);
$part1 = substr($sql, 0, $pos);
$part2 = substr($sql, $pos+1);            
$sql = $part1 . $val . $part2;
As a bonus you might save a few CPU cycles, because strpos and substr should be a little faster than regular expressions Wink (this is my blind guess, i didn't run any tests and i don't see any need for this, because the speed difference would be very small)

Greetings!
miau
#2

[eluser]Unknown[/eluser]
This bug is also present in CI 1.6.0. I actually found and fixed it just last week (smarter guy would have looked here first and found the fix miau suggested). My own fix has the same idea as miau's. The only difference worth mentioning is using the offset parameter of strpos. The fixed loop in DB_driver::compile_binds is as follows:

Code:
$offset = 0;
        foreach ($binds as $val)
        {
            $val = $this->escape($val);
                    
            // Just in case the replacement string contains the bind
            // character we'll temporarily replace it with a marker
            $val = str_replace($this->bind_marker, '{&#xbi;nd_marker%}', $val);
            
            //Calculating the position of next bind marker
            $pos = strpos($sql, $this->bind_marker, $offset) + strlen($this->bind_marker);
            
            //The piece of the query string to be handled this round
            $searchPiece = substr($sql, 0, $pos);
            
            //We know that there's only one bind marker to replace
            $searchPiece = str_replace($this->bind_marker, $val, $searchPiece);
            
            //Combining the modified piece with the rest of the query string
            $sql = $searchPiece.substr($sql, $pos);
            
            $offset = $pos;
        }

I really recommend that everyone use either of this fixes as the query binding isn't secure by default.




Theme © iAndrew 2016 - Forum software by © MyBB