Project

General

Profile

Actions

Bug #27858

closed

dbal fails parsing on '''

Added by Anonymous almost 13 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Must have
Assignee:
-
Category:
Database API (Doctrine DBAL)
Target version:
Start date:
2011-07-05
Due date:
% Done:

100%

Estimated time:
TYPO3 Version:
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

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

Actions #1

Updated by Xavier Perseguers almost 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.

Actions #2

Updated by Anonymous over 12 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

Actions #3

Updated by Mr. Hudson over 12 years ago

Patch set 1 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #4

Updated by Anonymous over 12 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

Actions #5

Updated by Mr. Hudson over 12 years ago

Patch set 2 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #6

Updated by Mr. Hudson over 12 years ago

Patch set 3 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #7

Updated by Mr. Hudson over 12 years ago

Patch set 4 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #8

Updated by Xavier Perseguers over 12 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
Actions #9

Updated by Xavier Perseguers over 12 years ago

  • Priority changed from Should have to Must have
Actions #10

Updated by Mr. Hudson over 12 years ago

Patch set 5 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #11

Updated by Mr. Hudson over 12 years ago

Patch set 6 of change I857aebb00efd1dc0752d42d436e6e9950a336370 has been pushed to the review server.
It is available at http://review.typo3.org/4192

Actions #12

Updated by Mr. Hudson over 12 years ago

Patch set 1 of change I929d5375480bd872b54fd458f67474ed21f29a3c has been pushed to the review server.
It is available at http://review.typo3.org/5713

Actions #13

Updated by Xavier Perseguers over 12 years ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100
Actions #14

Updated by Michael Stucki over 10 years ago

  • Project changed from 329 to TYPO3 Core
  • Category deleted (MS SQL Server)
Actions #15

Updated by Michael Stucki over 10 years ago

  • Category set to 999
Actions #16

Updated by Riccardo De Contardi over 6 years ago

  • Status changed from Resolved to Closed
Actions

Also available in: Atom PDF