Bug #27858
closed![Author: Anonymous](/images/anonymous.png?1718153102)
dbal fails parsing on '''
100%
Description
When using dbal with MSSQL, the parser fails when simple quotes are escaped by the adodb mssql driver.
Since MSSQL escapes simple quotes with a simple quote, the parser seems to think that a new statement begins and fatally crashes because no operator is set. Instead of crashing, dbal should check, that this is no error but an escaped simple quote.
Greets Tizian
Files
Updated by Xavier Perseguers about 13 years ago
- Status changed from New to Needs Feedback
Can you please give me the origin query (PHP code, SQL string, ...) that causes this behavior? In order for me to write a unit test reproducing the bug and hopefully solve it.
Updated by Anonymous about 13 years ago
Hello Xavier,
here the code as sent to you today:
/** * Get value in quotes from $parseString. * NOTICE: If a query being parsed was prepared for another database than MySQL this function should probably be changed * * @param string String from which to find value in quotes. Notice that $parseString is passed by reference and is shortend by the output of this function. * @param string The quote used; input either " or ' * @return string The value, passed through stripslashes() ! */ protected function getValueInQuotes(&$parseString, $quote) { /*** Thanks to Nils Blattner for the regexp and the support while doing this. */ if(preg_match('/' . $quote . $quote . '[^[:space:]]/', $parseString)) { $parseString = preg_replace('/' . $quote . '(([^' . $quote . ']*|' . $quote . $quote . ')*)' . $quote . '/', '$1', $parseString); } $parts = explode($quote, substr($parseString, 1)); $buffer = ''; foreach ($parts as $k => $v) { $buffer .= $v; $reg = array(); preg_match('/\\\\$/', $v, $reg); if ($reg AND strlen($reg[0]) % 2) { $buffer .= $quote; } else { $parseString = ltrim(substr($parseString, strlen($buffer) + 2)); return $this->parseStripslashes($buffer); } } }
This code can be added at the end of the ux_t3lib_sqlparser class so it will override the original method.
Greets
Tizian
Updated by Mr. Hudson about 13 years ago
Patch set 1 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Anonymous about 13 years ago
Hi there,
we finally managed to get this work!
Here the code:
/** * Get value in quotes from $parseString. * NOTICE: If a query being parsed was prepared for another database than MySQL this function should probably be changed * * @param string String from which to find value in quotes. Notice that $parseString is passed by reference and is shortend by the output of this function. * @param string The quote used; input either " or ' * @return string The value, passed through stripslashes() ! */ protected function getValueInQuotes(&$parseString, $quote) { /*** Thanks to Nils Blattner for the regexp and the support while doing this. */ $previousIsQuote = false; $inQuote = false; // Go through the whole string for ($c = 0; $c < strlen($parseString); $c++) { // If the parsed string character is the quote string if ($parseString{$c} === $quote) { // If we are already in a quote if ($inQuote) { // Was the previous a quote? if ($previousIsQuote) { // If yes, replace it by a \ $parseString{$c - 1} = '\\'; } // Invert the value $previousIsQuote = !$previousIsQuote; } else { // so we are in a quote since now $inQuote = true; } // So the parsed character is not a quote char and the previous char was a quote? so we are not in a quote anymore } elseif ($inQuote && $previousIsQuote) { $inQuote = false; $previousIsQuote = false; // So we are still in a quote and the previous is not a quote } else { $previousIsQuote = false; } } $parts = explode($quote, substr($parseString, 1)); $buffer = ''; foreach ($parts as $k => $v) { $buffer .= $v; $reg = array(); preg_match('/\\\\$/', $v, $reg); if ($reg AND strlen($reg[0]) % 2) { $buffer .= $quote; } else { $parseString = ltrim(substr($parseString, strlen($buffer) + 2)); return $this->parseStripslashes($buffer); } } }
IDEA: This might be refactored in a style that there could be a preExplodeParseStringHook (or something like this) that could be defined in the handler, so this would not be executed when using a MySQL handler for example (or everything else which quotes single quotes with backslashes).
Greets Tizian
Updated by Mr. Hudson almost 13 years ago
Patch set 2 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Mr. Hudson almost 13 years ago
Patch set 3 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Mr. Hudson almost 13 years ago
Patch set 4 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Xavier Perseguers almost 13 years ago
- Category set to MS SQL Server
- Status changed from Needs Feedback to Under Review
- Assignee set to Anonymous
- Target version set to 4.6.0-RC1
Updated by Xavier Perseguers almost 13 years ago
- Priority changed from Should have to Must have
Updated by Mr. Hudson almost 13 years ago
Patch set 5 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Mr. Hudson almost 13 years ago
Patch set 6 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192
Updated by Mr. Hudson almost 13 years ago
Patch set 1 of change I929d5375480bd872b54fd458f67474ed21f29a3c has been pushed to the review server.
It is available at http://review.typo3.org/5713
Updated by Xavier Perseguers almost 13 years ago
- Status changed from Under Review to Resolved
- % Done changed from 0 to 100
Updated by Michael Stucki over 10 years ago
- Project changed from 329 to TYPO3 Core
- Category deleted (
MS SQL Server)
Updated by Riccardo De Contardi almost 7 years ago
- Status changed from Resolved to Closed