-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PREG_QUOTE and SQL String Binding #655
Comments
There is a line that removes \. and replaces with ".". Why not get the preg_quote char list, and remove hyphens and periods and use preg_replace?? Proposed change below. OR, make it overwritable. $escapedValue = preg_replace('/([+*?\[^\]$(){}=!<>|:])/', "\\\\$1",trim( $escapedValue,$this->db->escapeChar)); protected function matchNamedBinds(string $sql, array $binds)
{
foreach ($binds as $placeholder => $value)
{
$escapedValue = $this->db->escape($value);
// In order to correctly handle backlashes in saved strings
// we will need to preg_quote, so remove the wrapping escape characters
// otherwise it will get escaped.
if (is_array($value))
{
foreach ($value as &$item)
{
$item = preg_quote($item, '|');
}
$escapedValue = '(' . implode(',', $escapedValue) . ')';
}
else
{
$escapedValue = preg_replace('/([+*?\[^\]$(){}=!<>|:])/', "\\\\$1",trim( $escapedValue,$this->db->escapeChar));
}
$sql = preg_replace('|:' . $placeholder . '(?!\w)|', $escapedValue, $sql);
}
return $sql;
} |
I have no problem with the second solution. If you wanted to make a PR for it that would be great. What issues were you running into, exactly, with the SQLSRV syntax? I'm not familiar enough with that variant. |
By default the database driver was escaping hyphens. When we use part numbers it would do 006038\-8.000. SQL Server takes this literally and doesn't need escaped. Everything seems to work on my end. But I haven't done any extreme testing yet. Here are the lines I changed plus my driver. I won't create a PR until I test it more. https://github.com/JakeAi/MinnichRW/blob/master/system/Database/BaseConnection.php#L244 |
I'm definitely looking forward to the PR. I haven't dug back through the logic enough yet, but why would the BaseConnection's escapeChar list need to change? Seems like overriding that in SQLSRV's Connection class would handle what was needed? |
Not sure entirely, as I am still trying to learn all of the logic. I am trying to make it change in the driver as much as possible but the function matchNamedBinds (in query.php) keeps escaping characters, and they won't work in SQL Server. The |
I just pushed a change that seems to fix things for both MySQL and PostgreSQL though it's far from ideal. I think this might help your issue out, also. |
Seems to work for me. I have also noticed that the
Is the the best method? Because the regex in that function creates %0[0-8bcef] which turns our 0s into a potential "non displayable" and strips them. But it also breaks the This is what it looks like without the override. Just look at the where statement
and with the override
|
Are you saying that this problem is still happening even after removing the preg_replace and converting it to strtr? |
That is correct. I am getting the sql strings from SQL Server Profiler which gets the absolute final sql. function remove_invisible_characters($str, $url_encoded = true)
{
$non_displayables = [];
// every control character except newline (dec 10),
// carriage return (dec 13) and horizontal tab (dec 09)
if ($url_encoded)
{
$non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15
$non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31
}
$non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
do
{
$str = preg_replace($non_displayables, '', $str, -1, $count);
} while ($count);
return $str;
} By default the URL_Encoded is set to true. I didn't know that at first so in my driver i made it false. But the regex takes my '000653-00000', makes a like '%000653-00000%' but the |
Hm. Interesting. That's straight from CI3 and I'm not overly up to speed on what it's for or how it's used in the other drivers so I will have to do some research. Have you checked CI3's driver to see how they handle it? |
@lonnieezell, I looked into CI3 and found a mismatch. protected function _escapeString(string $str): string
{
return str_replace("'", "''", remove_invisible_characters($str));
} CI3 - https://github.com/bcit-ci/CodeIgniter/blob/develop/system/database/DB_driver.php#L1121 protected function _escape_str($str)
{
return str_replace("'", "''", remove_invisible_characters($str, FALSE));
} |
@lonnieezell I posted a pull request which behaves exactly like CI3. When I removed the escapeString from the MYSQLI Driver I had the same issue, but not on CI3. Which came down to that function not having false passed through. |
I think we're good on this, then. I merged your PR. Closing this unless we run into other issues. |
The function \CodeIgniter\Database\Query matchNamedBinds() uses preg_quote to escape some characters. This is a hindrance with SQLSRV as the backslashes are taken literally. Is there a way to override this function in the driver since it's being loaded as a new query in many base functions?
Adding the line (below) fixes the issue.
The text was updated successfully, but these errors were encountered: