1
0
mirror of https://github.com/maximebf/php-debugbar.git synced 2025-06-09 23:55:00 +02:00

Fix warning on resource query parameter (#744)

Fix PHP 8 warning in `TracedStatement::getSqlWithParameters()` when a stream resource was bound.

```
TypeError: mb_check_encoding(): Argument #1 ($value) must be of type array|string|null, resource given
```

This can happen when e.g. [binding `PDO::PARAM_LOB`](docs) to your query.

[docs]: https://www.php.net/manual/en/pdo.lobs.php
This commit is contained in:
Michaël Jacobs 2025-02-26 15:54:52 +01:00 committed by GitHub
parent 4b3d5f1afe
commit 0615a183c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 0 deletions

View File

@ -76,6 +76,9 @@ class TracedStatement
public function checkParameters(array $params) : array
{
foreach ($params as &$param) {
if (is_resource($param)) {
$param = $this->getResourceContents($param);
}
if (!mb_check_encoding($param ?? '', 'UTF-8')) {
$param = '[BINARY DATA]';
}
@ -83,6 +86,27 @@ class TracedStatement
return $params;
}
/**
* @param resource $stream
*/
private function getResourceContents($stream, int $length = -1) : string
{
$meta = stream_get_meta_data($stream);
$isSeekable = (bool) $meta['seekable'];
if (! $isSeekable) {
return sprintf('[resource id #%d]', get_resource_id($stream));
}
fseek($stream, 0);
$contents = stream_get_contents($stream, $length);
if (-1 !== $length && ! feof($stream)) {
$contents .= '…';
}
fseek($stream, 0, SEEK_END);
return $contents;
}
/**
* Returns the SQL string used for the query, without filled parameters
*

View File

@ -119,6 +119,42 @@ class TracedStatementTest extends DebugBarTestCase
$this->assertEquals($expected, $result);
}
/**
* Check if stream resource query parameters are replaced without triggering a type error since PHP 8.0.0.
* This can happen when e.g. binding `PDO::PARAM_LOB` to your prepared statement.
*
* @link https://www.php.net/manual/en/pdo.lobs.php
*/
public function testReplacementParamsContainingLargeObjectResourceGeneratesCorrectString()
{
$sql = 'UPDATE user SET signature = :signature WHERE id = :id';
$seekableResource = fopen('php://memory', 'r+');
fputs($seekableResource, 'Signature from rewindable LOB stream resource.');
$params = [
'id' => 1234,
'signature' => $seekableResource,
];
$traced = new TracedStatement($sql, $params);
$expected = 'UPDATE user SET signature = "Signature from rewindable LOB stream resource." WHERE id = "1234"';
$result = $traced->getSqlWithParams('"');
$this->assertEquals($expected, $result);
$unseekableResource = fopen('php://stdout', 'r');
$params = [
'id' => 1234,
'signature' => $unseekableResource,
];
$traced = new TracedStatement($sql, $params);
$expected = sprintf('UPDATE user SET signature = "[resource id #%d]" WHERE id = "1234"', (int) $unseekableResource);
$result = $traced->getSqlWithParams('"');
$this->assertEquals($expected, $result);
}
/**
* Check if literal `NULL` query parameters are replaced without triggering a deprecation warning since PHP 8.0.0.
* This can happen when e.g. binding `PDO::PARAM_NULL` to your prepared statement.