Loading core/lib/Drupal/Core/Database/Connection.php +6 −2 Original line number Diff line number Diff line Loading @@ -727,8 +727,12 @@ public function query($query, array $args = [], $options = []) { // semicolon) is not allowed unless the option is set. Allowing // semicolons should only be needed for special cases like defining a // function or stored procedure in SQL. Trim any trailing delimiter to // minimize false positives. $query = rtrim($query, "; \t\n\r\0\x0B"); // minimize false positives unless delimiter is allowed. $trim_chars = " \t\n\r\0\x0B"; if (empty($options['allow_delimiter_in_query'])) { $trim_chars .= ';'; } $query = rtrim($query, $trim_chars); if (strpos($query, ';') !== FALSE && empty($options['allow_delimiter_in_query'])) { throw new \InvalidArgumentException('; is not supported in SQL strings. Use only one statement at a time.'); } Loading core/tests/Drupal/Tests/Core/Database/ConnectionTest.php +54 −0 Original line number Diff line number Diff line Loading @@ -576,4 +576,58 @@ public function testNamespaceDefault() { $this->assertSame('Drupal\Tests\Core\Database\Stub', $connection->getConnectionOptions()['namespace']); } /** * Test rtrim() of query strings. * * @dataProvider provideQueriesToTrim */ public function testQueryTrim($expected, $query, $options) { $mock_pdo = $this->getMockBuilder(StubPdo::class) ->setMethods(['execute', 'prepare', 'setAttribute']) ->getMock(); // Ensure that PDO::prepare() is called only once, and with the // correctly trimmed query string. $mock_pdo->expects($this->once()) ->method('prepare') ->with($expected) ->willReturnSelf(); $connection = new StubConnection($mock_pdo, []); $connection->query($query, [], $options); } /** * Dataprovider for testQueryTrim(). * * @return array * Array of arrays with the following elements: * - Expected trimmed query. * - Padded query. * - Query options. */ public function provideQueriesToTrim() { return [ 'remove_semicolon' => [ 'SELECT * FROM test', 'SELECT * FROM test;', [], ], 'keep_trailing_semicolon' => [ 'SELECT * FROM test;', 'SELECT * FROM test;', ['allow_delimiter_in_query' => TRUE], ], 'remove_semicolon_with_whitespace' => [ 'SELECT * FROM test', 'SELECT * FROM test; ', [], ], 'keep_trailing_semicolon_with_whitespace' => [ 'SELECT * FROM test;', 'SELECT * FROM test; ', ['allow_delimiter_in_query' => TRUE], ], ]; } } Loading
core/lib/Drupal/Core/Database/Connection.php +6 −2 Original line number Diff line number Diff line Loading @@ -727,8 +727,12 @@ public function query($query, array $args = [], $options = []) { // semicolon) is not allowed unless the option is set. Allowing // semicolons should only be needed for special cases like defining a // function or stored procedure in SQL. Trim any trailing delimiter to // minimize false positives. $query = rtrim($query, "; \t\n\r\0\x0B"); // minimize false positives unless delimiter is allowed. $trim_chars = " \t\n\r\0\x0B"; if (empty($options['allow_delimiter_in_query'])) { $trim_chars .= ';'; } $query = rtrim($query, $trim_chars); if (strpos($query, ';') !== FALSE && empty($options['allow_delimiter_in_query'])) { throw new \InvalidArgumentException('; is not supported in SQL strings. Use only one statement at a time.'); } Loading
core/tests/Drupal/Tests/Core/Database/ConnectionTest.php +54 −0 Original line number Diff line number Diff line Loading @@ -576,4 +576,58 @@ public function testNamespaceDefault() { $this->assertSame('Drupal\Tests\Core\Database\Stub', $connection->getConnectionOptions()['namespace']); } /** * Test rtrim() of query strings. * * @dataProvider provideQueriesToTrim */ public function testQueryTrim($expected, $query, $options) { $mock_pdo = $this->getMockBuilder(StubPdo::class) ->setMethods(['execute', 'prepare', 'setAttribute']) ->getMock(); // Ensure that PDO::prepare() is called only once, and with the // correctly trimmed query string. $mock_pdo->expects($this->once()) ->method('prepare') ->with($expected) ->willReturnSelf(); $connection = new StubConnection($mock_pdo, []); $connection->query($query, [], $options); } /** * Dataprovider for testQueryTrim(). * * @return array * Array of arrays with the following elements: * - Expected trimmed query. * - Padded query. * - Query options. */ public function provideQueriesToTrim() { return [ 'remove_semicolon' => [ 'SELECT * FROM test', 'SELECT * FROM test;', [], ], 'keep_trailing_semicolon' => [ 'SELECT * FROM test;', 'SELECT * FROM test;', ['allow_delimiter_in_query' => TRUE], ], 'remove_semicolon_with_whitespace' => [ 'SELECT * FROM test', 'SELECT * FROM test; ', [], ], 'keep_trailing_semicolon_with_whitespace' => [ 'SELECT * FROM test;', 'SELECT * FROM test; ', ['allow_delimiter_in_query' => TRUE], ], ]; } }