php-imagine / Imagine

PHP Object Oriented image manipulation library
https://imagine.readthedocs.io
Other
4.42k stars 529 forks source link

Issue loading binary image on PHP8 [GD] #764

Closed Mark-H closed 3 years ago

Mark-H commented 3 years ago

Issue description

Provided the raw binary contents of the same image, the following works on 7.4.12, but on 8.0.2 throws an exception:

$original = $imagine->load($imageContent); 
[Imagine\Exception\RuntimeException] An image could not be created from the given input #0 vendor/imagine/imagine/src/Gd/Imagine.php(108): Imagine\Gd\Imagine->doLoad('\x89PNG\r\n\x1A\n\x00\x00\x00\rIHD...', Object(Imagine\Image\Metadata\MetadataBag))

What version of Imagine are you using?

v1.2.4

What's the PHP version you are using?

Fails on:

PHP 8.0.2 (cli) (built: Feb  9 2021 17:04:02) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.2, Copyright (c) Zend Technologies

with GD config:

gd

GD Support => enabled
GD Version => bundled (2.1.0 compatible)
FreeType Support => enabled
FreeType Linkage => with freetype
FreeType Version => 2.6.5
GIF Read Support => enabled
GIF Create Support => enabled
JPEG Support => enabled
libJPEG Version => 9 compatible
PNG Support => enabled
libPNG Version => 1.6.37
WBMP Support => enabled
XBM Support => enabled
WebP Support => enabled
BMP Support => enabled
TGA Read Support => enabled

Directive => Local Value => Master Value
gd.jpeg_ignore_warning => 1 => 1

Works as expected on:

PHP 7.4.12 (cli) (built: Nov 30 2020 13:28:43) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

with GD config:

gd

GD Support => enabled
GD Version => bundled (2.1.0 compatible)
FreeType Support => enabled
FreeType Linkage => with freetype
FreeType Version => 2.6.5
GIF Read Support => enabled
GIF Create Support => enabled
JPEG Support => enabled
libJPEG Version => 9 compatible
PNG Support => enabled
libPNG Version => 1.6.37
WBMP Support => enabled
XBM Support => enabled
WebP Support => enabled
BMP Support => enabled
TGA Read Support => enabled

Directive => Local Value => Master Value
gd.jpeg_ignore_warning => 1 => 1

On localhost powered by MAMP Pro, macOS 11.3.

What's the imaging library you are using [gd/imagick/gmagick/any]?

GD

What's the imaging library configuration

Included above

Minimal PHP code to reproduce the error:

$imagine = new Imagine\Gd\Imagine();
if (ExifMetadataReader::isSupported()) {
    // Use the Exif metadata reader to be able of accessing the orientation
    $imagine->setMetadataReader(new ExifMetadataReader());
}
$original = $imagine->load($imageContent); 

$imageContent is provided from a file upload and read into memory in its binary form (basically a glorified file_get_contents on the upload file, though there's some abstraction going on that also allows it to work on S3 and such).

I've compared the output of bin2hex($imageContent) on both PHP versions which are identical, so it doesn't seem to be an issue with loading the file contents. But I'm not sure how to debug this from here.

Removing the metadata reader does not have any effect.

This is the test image I was using, but it seems to affect all images I try it with.

dimensions-wide_

ausi commented 3 years ago

What happens if you execute the following code:

$pngContent = hex2bin('89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c4890000000a49444154789c63000100000500010d0a2db40000000049454e44ae426082');

var_dump((new \Imagine\Gd\Imagine())->load($pngContent));
var_dump(imagecreatefromstring($pngContent));
Mark-H commented 3 years ago

On 7.4.12:

object(Imagine\Gd\Image)[45]
  private 'resource' => resource(237, gd)
  private 'layers' => null
  private 'palette' => 
    object(Imagine\Image\Palette\RGB)[42]
      private 'parser' => 
        object(Imagine\Image\Palette\ColorParser)[41]
      private 'profile' => null
  protected 'metadata' => 
    object(Imagine\Image\Metadata\MetadataBag)[43]
      private 'data' => 
        array (size=0)
          empty
  private 'classFactory' (Imagine\Image\AbstractImage) => 
    object(Imagine\Factory\ClassFactory)[48]

resource(245, gd)

On 8.0.2:

object(Imagine\Gd\Image)#55 (5) {
  ["resource":"Imagine\Gd\Image":private]=>
  object(GdImage)#54 (0) {
  }
  ["layers":"Imagine\Gd\Image":private]=>
  NULL
  ["palette":"Imagine\Gd\Image":private]=>
  object(Imagine\Image\Palette\RGB)#43 (2) {
    ["parser":"Imagine\Image\Palette\RGB":private]=>
    object(Imagine\Image\Palette\ColorParser)#47 (0) {
    }
    ["profile":"Imagine\Image\Palette\RGB":private]=>
    NULL
  }
  ["metadata":protected]=>
  object(Imagine\Image\Metadata\MetadataBag)#44 (1) {
    ["data":"Imagine\Image\Metadata\MetadataBag":private]=>
    array(0) {
    }
  }
  ["classFactory":"Imagine\Image\AbstractImage":private]=>
  object(Imagine\Factory\ClassFactory)#50 (0) {
  }
}
object(GdImage)#55 (0) {
}

When feeding that the test file it gives the same result (resource on 7.4.12, GdImage on 8.0.2).

(Also, thanks for responding so quickly, and on the weekend too!)

Mark-H commented 3 years ago

Okay so running that test code had me super confused, as it was suddenly allowing to load() the same image that would continue to fail as part of my upload code.

After some more digging, it turns out the upload code ran into a dependency conflict. An older version of another addon in the same CMS installation was loading imagine v1.2.3, and that got used in the upload code. But not when I ran the test code from a different file. 🙈

So - bottom line - it was a problem on this end and fixed with v1.2.4. Thanks for the quick support!