[php-src] Issue #10834: exif_read_data() cannot read smaller stream wrapper chunk sizes

From: 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

« previous php.bugs (#243896) next »