[php-src] PR #24242: ext/phar: 32-bit/64-bit divergence parsing tar entries with size ≥ 2 GiB (uint32_t → zend_off_t)
| From: | PavlNekrasov | Date: | Sat, 10 Oct 2026 15:01:44 +0000 |
| Subject: | [php-src] PR #24242: ext/phar: 32-bit/64-bit divergence parsing tar entries with size ≥ 2 GiB (uint32_t → zend_off_t) | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39317@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24242
Author: PavlNekrasov
**Description:**
The tar header's
size field is read as uint32_t and passed as-is to
php_stream_seek() (offset is signed zend_off_t). On 32-bit,
zend_off_t is int32, so sizes with the high bit set wrap into a negative
offset — UBSan flags it, getSize() returns a negative value, and the
corrupt/truncated check never triggers. On 64-bit the same size fits and the entry is correctly
rejected as truncated.
**Reproducer:**
```sh
php -d display_errors=1 -r '
var_dump(PHP_INT_SIZE);
try {
$phar = new PharData("/test.tar");
echo "Parsed, entries: ", count($phar), PHP_EOL;
foreach ($phar as $file) {
echo "Name: ", $file->getFilename(), PHP_EOL;
echo "Size: ", $file->getSize(), PHP_EOL;
echo "Path: ", $file->getPathname(), PHP_EOL;
echo "RealPath: ", $file->getRealPath(), PHP_EOL;
echo "Readable: ", var_export($file->isReadable(), true), PHP_EOL;
echo "--- content (first 64 bytes) ---", PHP_EOL;
$fp = $file->openFile("r");
echo bin2hex($fp->fread(64)), PHP_EOL;
}
} catch (Throwable $e) {
echo get_class($e), ": ", $e->getMessage(), PHP_EOL;
}'
```
With test.tar (entry bigfile, header size 0xC0000000 =
3221225472):
**32-bit:**
```
int(4)
Parsed, entries: 1
Name: bigfile
Size: -1073741824
Path: phar:///test.tar/bigfile
RealPath:
Readable: true
```
UBSan:
```
# SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /php-8.3.31/ext/phar/tar.c:576:21
# /php-8.3.31/ext/phar/tar.c:581:4: runtime error: implicit conversion from type
'uint32_t' (aka 'unsigned int') of value 3221225472 (32-bit, unsigned) to type
'zend_off_t' (aka 'int') changed the value to -1073741824 (32-bit, signed)
```
**64-bit:**
```
int(8)
UnexpectedValueException: phar error: "/host/test.tar" is a corrupted tar file (truncated)
```
**Env:** PHP 8.3.31; 32-bit and 64-bit builds.
Found by Linux Verification Center (linuxtesting.org) with SVACE