[php-src] Issue #10834: exif_read_data() cannot read smaller stream wrapper chunk sizes
| From: | dotpointer | Date: | Sun, 12 Mar 2023 15:22:58 +0000 |
| Subject: | [php-src] Issue #10834: exif_read_data() cannot read smaller stream wrapper chunk sizes | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-243896@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/10834
Author: dotpointer
### Description
exif_read_data() outputs the warning below when it reads from a stream wrapper source
and the stream chunk size that is set by stream_set_chunk_size() is too small. What is
considered a too small chunk size seems to depend on the file size and maybe the EXIF data size
inside it. On a 271 KB JPEG it was 113, but on a 1,1M JPEG was 7397. Sometimes even the default
chunk size is too small and it needs to be adjusted to work.
The example stream wrapper class is a modified version of the VariableStream example from the
manual:
https://www.php.net/manual/en/stream.streamwrapper.example-1.php
I have tested this on Debian Linux 11 with PHP 7.4.33 and on the same system in a Docker environment
with PHP 8.1.16, the bug is in both versions.
I found JPEG files with EXIF data on the Lorem Picsum page, but I have tried other sources too with
the same error:
https://picsum.photos/1920/1080
If there is something wrong with the example code please tell me how to correct it so I can learn
something please. :blush I have tried different variants of this code like writing to the stream
before reading it using cURL calls which makes no difference and also passing a fopen() file handle
that reads image file directly which makes the bug disappear.
The PHP code:
```php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
# set the path to a (JPEG) image file with EXIF data
# a big file like +1 MB is recommended
define('IMAGE_FILE', './example.jpg');
class VariableStream {
var $data;
var $position;
function stream_close() {
# echo "Stream close\n";
return true;
}
function stream_eof() {
# echo 'Stream eof - '.($this->position >= strlen($this->data ?
'Yes' : 'No'))."\n";
return $this->position >= strlen($this->data);
}
function stream_open($path, $mode, $options, &$opened_path) {
# echo "Stream opened\n";
$this->position = 0;
$this->data = file_get_contents(IMAGE_FILE);
return true;
}
function stream_seek($offset, $whence) {
# echo "Stream seek $offset $whence\n";
switch ($whence) {
case SEEK_SET:
if ($offset < strlen($this->data) && $offset >= 0) {
$this->position = $offset;
return true;
} else {
return false;
}
break;
case SEEK_CUR:
if ($offset >= 0) {
$this->position += $offset;
return true;
} else {
return false;
}
break;
case SEEK_END:
if (strlen($this->data) + $offset >= 0) {
$this->position = strlen($this->data) + $offset;
return true;
} else {
return false;
}
break;
default:
return false;
}
}
function stream_read($count) {
# echo "Stream read\n";
$ret = substr($this->data, $this->position, $count);
$this->position += strlen($ret);
return $ret;
}
function stream_tell() {
# echo 'Stream tell: '.$this->position."\n";
return $this->position;
}
}
stream_wrapper_register('var', 'VariableStream')
or die('Failed to register protocol');
$fp = fopen('var://myvar', 'rb');
# try different chunk sizes here to find
# the threshold where the error disappear
stream_set_chunk_size($fp, 50);
# error appear after this line
exif_read_data($fp);
fclose($fp);
?>
```
Resulted in this output:
```
Warning: exif_read_data(): Error reading from file: got=x00C2(=194) != itemlen-2=x00DE(=222) in
example.php on line 85
Warning: exif_read_data(): Invalid JPEG file in example.php on line 85
```
But I expected this output instead:
```
No output expected.
```
### PHP Version
PHP 8.1.16
### Operating System
Debian 11