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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions