Skip to content

PDO SQLite driver: escapeBinary() throws TypeError on binary data with NUL bytes (PHP 8.5) #474

Description

@zeleznypa

Version

  • dibi 5.1
  • PHP 8.5.8
  • Driver: pdo with a sqlite: DSN (Dibi\Drivers\PdoDriver)

Description

Dibi\Drivers\PdoDriver::escapeBinary() has no dedicated sqlite branch, so for a SQLite connection it falls through to the default arm:

default => $this->connection->quote($value, PDO::PARAM_LOB),

On PHP 8.5, PDO::quote() for the SQLite driver returns false when the value contains a NUL byte (\0). Because escapeBinary(): string is typed, this surfaces as a TypeError:

TypeError: Dibi\Drivers\PdoDriver::escapeBinary(): Return value must be of type string, false returned

The native ext-sqlite3 driver (Dibi\Drivers\SqliteDriver::escapeBinary()) already handles this correctly and does not use quote():

public function escapeBinary(string $value): string
{
    return "X'" . bin2hex($value) . "'";
}

So the PDO SQLite driver is inconsistent with the native SQLite driver for binary values.

Steps to reproduce

Minimal reproduction on PHP 8.5.8 (dibi 5.1, PDO SQLite):

$connection = new Dibi\Connection(['driver' => 'pdo', 'dsn' => 'sqlite::memory:']);
$binId = hex2bin('007f138c2c007ce8849e378f4e374e6a'); // UUIDv7, starts with a NUL byte

$connection->getDriver()->escapeBinary($binId); // TypeError
TypeError: Dibi\Drivers\PdoDriver::escapeBinary(): Return value must be of type string, false returned

Full runnable repro: https://github.com/zeleznypa/dibi-binary-issue

Proposed fix

Add a sqlite branch mirroring the native driver:

 public function escapeBinary(string $value): string
 {
     return match ($this->driverName) {
         'odbc' => "'" . str_replace("'", "''", $value) . "'",
+        'sqlite' => "X'" . bin2hex($value) . "'",
         'sqlsrv' => '0x' . bin2hex($value),
         default => $this->connection->quote($value, PDO::PARAM_LOB),
     };
 }

Note

PdoDriver::escapeText() has the same structure (SQLite also falls through to quote()), so text values carrying NUL bytes hit the same TypeError. Binary data should use %bin, so escapeBinary() is the key fix — happy to address escapeText() too if you prefer. I can open a PR with the fix and a test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions