dg / dibi

Dibi - smart database abstraction layer

Home Page:https://dibiphp.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Surplus 'N' in front of string param

TumaMilan opened this issue · comments

Version: 4.2.6 (but from 4.1.x)

Bug Description

When using N in front of SQL string param, calling query() adds another N, so result is NN'param'. SqlsrvDriver only.

Steps To Reproduce

Using sqlsrv driver:
$this->db->query("SELECT * FROM table WHERE N'A' = N'A'");
(where $this->db is Dibi\Connection)
The resulting SQL is SELECT * FROM table WHERE NN'A' = NN'A' and SQL server notices Wrong syntax near text A (translated from Czech error description)

Expected Behavior

No conversion of right SQL code.

Possible Solution

I have no direct solution. From version DIBI 4.1 is added N to function escapeText() of SqlsrvDriver.php. But escaping of escaped text does waste. Specifically this issue has origin in function cb(), callback of preg_replace_callback of function translate() of Translator.php. Calling

		} elseif ($matches[3]) { // SQL strings: '...'
			return $this->driver->escapeText(str_replace("''", "'", $matches[4]));
		} ...

adds another N in front (behind) of existing N.
Unfortunately I can't make it work by not using 'N'. The query is part of contribute datagrid and is managed by him. Not this query, of course:)

I suggest

  • not using 'N' (at least optionally)
  • edit regex to ignore N' (N + apostrophe)

Thanks
Milan Tůma

Hm, I've commented it this afternoon but comment is missing - maybe didn't submit the form.

You wrote ...escaping of escaped text does waste... thats corrent. If you are 100% sure that SQL injection cannot occure, e.g. the SQL string cames from $sql = $connection->translate(), you should use %SQL modifier:

$sql = $db->translate('SELECT * FROM table WHERE ? = ?', 'A', 'A');
$db->query('%SQL', $sql);  # dibi does not touch it

But must be 100% sure, otherwise it's an SQL injection gateway.

Unfortunately I can't make it work by not using 'N'. The query is part of contribute datagrid

Can you link the specific query that's causing problem?

If you are 100% sure that SQL injection cannot occure, e.g. the SQL string cames from $sql = $connection->translate(), you should use %SQL modifier:

I cannot do any changes to source of Ublaboo datagrid. The algorythm of questioning is automatic. The query is translated twice. Issue is only on combination UblabooDatagrid->Dibi Fluent->MSSQL

Ublaboo datagrid

Sorry, Ublaboo datagrid renamed to Contribute datagrid. But not totally, so it is little confusing 😁

Can you link the specific query that's causing problem?

I'm afraid I don't understand you. If you mean SQL query, so any query containing apostrophe. Any text value. Datagrid does 2 translations of query, second pass destroys the query. I can't influence this.

I tried to change the regex and callback in Translator.php to identify N before apostrophe. But it is not easy and can't guarantee full functionality of function translate(). I decided to extend class SqlsrvDriver with my SqlsrvsitmpDriver:

<?php
declare(strict_types=1);

namespace Dibi\Drivers;

class SqlsrvsitmpDriver extends SqlsrvDriver implements \Dibi\Driver
{
    public function escapeText(string $value): string
    {
        return "'" . str_replace("'", "''", $value) . "'"; // N removed
    }
}

and in configuration use

dibi:
	driver: sqlsrvsitmp

Removing N could be parametric - for example by new item in dibi options (UseNvarchar = false) in configuration. This setting would consume __construct() method of driver class and pass it to method escapeText(string $value) by local field. But for my use case is it not necessary.
Milan Tůma