-
Notifications
You must be signed in to change notification settings - Fork 7.8k
exif_read_data() cannot read smaller stream wrapper chunk sizes #10834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This code is the problem: php-src/main/streams/streams.c Lines 748 to 753 in e2ec59f
Since you have your own defined stream, the if triggers and breaks early, which results in not reading all the necessary data. I think we might need to check for user-defined stream here too. If that user-defined stream would do reads from a stream as well, then this condition will still work as expected. In your case it would mean that the condition is not hit because you're using the file stream type indirectly because of the file_get_contents. |
Changing the if to include userspace streams results in a failure of the test By adding such an exception we essentially move the greedy/non-greedy problem to whatever underlying code the userspace stream is using. If the userspace stream has all the data available already (like in OP's case), I don't think there's a need to be non-greedy. If the userspace stream does not yet have all data available, then itself probably uses a stream and then the decision for greedy/non-greedy will fall on that stream. So I think it would be okay to change this. |
…chunk sizes Exif uses php_stream_read() to read data from the stream and process it. In this case, it's a userspace stream. Userspace streams can either by local or url streams. In 5060fc2 and subsequently 0a45e8f, the behaviour of the check was changed twice in total. In the latter commit the description talks about exceptions for streams that are local to the process. It looks like the exception for local userspace streams was forgotten. This patch updates the check such that local userspace streams also read greedily, while keeping url userspace streams unchanged. This also updates the existing test to test both local and url userspace streams.
…chunk sizes Exif uses php_stream_read() to read data from the stream and process it. In this case, it's a userspace stream. Userspace streams can either by local or url streams. In 5060fc2 and subsequently 0a45e8f, the behaviour of the check was changed twice in total. In the latter commit the description talks about exceptions for streams that are local to the process. It looks like the exception for local userspace streams was forgotten. This patch updates the check such that local userspace streams also read greedily, while keeping url userspace streams unchanged. This also updates the existing test to test both local and url userspace streams.
…chunk sizes php_stream_read() may return less than the requested amount of bytes by design. This patch introduces a static function for exif which reads from the stream in a loop until all the requested bytes are read. Test was Co-authored-by: dotpointer
…chunk sizes php_stream_read() may return less than the requested amount of bytes by design. This patch introduces a static function for exif which reads from the stream in a loop until all the requested bytes are read. Test was Co-authored-by: dotpointer
* PHP-8.1: Fix GH-10834: exif_read_data() cannot read smaller stream wrapper chunk sizes
* PHP-8.2: Fix GH-10834: exif_read_data() cannot read smaller stream wrapper chunk sizes
Description
exif_read_data()
outputs the warning below when it reads from a stream wrapper source and the stream chunk size that is set bystream_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:
Resulted in this output:
But I expected this output instead:
PHP Version
PHP 8.1.16
Operating System
Debian 11
The text was updated successfully, but these errors were encountered: