[php-src] Issue #9885: [PHP 8.0.25] Function JIT may skip implicit type conversion in some cases, causing an error
| From: | mszabo-wikia | Date: | Thu, 03 Nov 2022 13:14:35 +0000 |
| Subject: | [php-src] Issue #9885: [PHP 8.0.25] Function JIT may skip implicit type conversion in some cases, causing an error | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-242744@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/9885
Author: mszabo-wikia
### Description
Hello,
We observed that the following code throws a TypeError when function JIT is enabled:
```php
<?php
class ContentReviewLiveRevisionStorage implements LiveRevisionStorage {
private const CURRENT_REVIEWED_REVISIONS_TABLE = 'current_reviewed_revisions';
private $lb;
public function __construct( ILoadBalancer $lb ) {
$this->lb = $lb;
}
public function getRevisionID( int $wikiId, int $pageId ): ?int {
$dbr = $this->lb->getConnection( DB_REPLICA );
$revision = $dbr->selectField(
self::CURRENT_REVIEWED_REVISIONS_TABLE,
'revision_id',
[
'wiki_id' => $wikiId,
'page_id' => $pageId,
]
);
return $revision === false ? null : $revision;
}
}
```
selectField in this context ultimately ends up calling mysqli::query and
mysqli::fetch_row, then returns the first element from the result row via
reset().[1]
Due to the data types in the table, $revision will then either be a numeric string, or
false. Thus, it should be implicitly convertible to int if it is a numeric
string, since strict types are not enabled here—but with function JIT, this method instead throws:
```
TypeError from line 28 of
/extensions/fandom/FandomIncludes/src/ResourceLoader/Storage/ContentReviewLiveRevisionStorage.php:
Fandom\Includes\ResourceLoader\Storage\ContentReviewLiveRevisionStorage::getRevisionID(): Return
value must be of type ?int, string returned
```
This error does not occur with tracing JIT.
I attempted to create a reproduction class that would do something similar (query a table via
mysqli, fetch the first item of a result row using reset() and return
$value === false ? null : $value from a method declared to return ?int),
then invoked this in a loop. Unfortunately I was unable to reproduce the error with the synthetic
attempt. I will update this issue if I do manage to somehow create a consistent reproducer.
Thanks in advance!
---
[1] https://github.com/wikimedia/mediawiki/blob/e9f9d892ab4cb5f8befc9e2b6753c97e26c2bb46/includes/libs/rdbms/database/Database.php#L1839
### PHP Version
PHP 8.0.25
### Operating System
_No response_