Skip to content

AVIF images misdetected as HEIF after introducing HEIF support in getimagesize() #20201

Closed

Description

@andypost

Description

After commit dfac2da PHP incorrectly detects certain AVIF files as HEIF.

The issue arises because both formats use the same ISOBMFF (.heif) container and share the mif1 major brand.
Current PHP logic checks only the major_brand and stops, even when the compatible_brands list includes avif.

Example test file header:

size: 0x0000001C
boxtype: 'ftyp'
major_brand: 'mif1'
minor_version: 0
compatible_brands: ['mif1', 'avif', 'miaf']

PHP currently classifies this as IMAGE_FILETYPE_HEIF, though it is an AVIF image.

Expected result:
Files that include 'avif' in compatible_brands should be recognized as IMAGE_FILETYPE_AVIF.

Actual result:
They are recognized as IMAGE_FILETYPE_HEIF.

Environment:

- PHP 8.3.x / 8.4.x
- GD enabled (bundled)
- libavif < 1.2.0 (no experimental HEIF support)
- Ubuntu Noble / Debian Testing
$file = 'test.avif';
$info = getimagesize($file);
var_dump($info[2]); // Expected IMAGETYPE_AVIF, got IMAGETYPE_HEIF

before 8.5 it returns int(19) but on 8.5 int(20)

Possible fix:
When parsing ftyp, prefer avif if it appears in compatible_brands, or parse all compatible brands before deciding on type.

Related references:

PHP Version

PHP 8.5.0RC2 (cli) (built: Oct  8 2025 09:46:31) (NTS)
Copyright (c) The PHP Group
Built by Alpine Linux aports
Zend Engine v4.5.0RC2, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.0RC2, Copyright (c), by Zend Technologies

Operating System

Ubuntu

Activity

  1. andypost commented on Oct 17, 2025

    @andypost
    ContributorAuthor
  2. andypost commented on Oct 17, 2025

    @andypost
    ContributorAuthor
  3. andypost commented on Oct 17, 2025

    @andypost
    ContributorAuthor

    fixed test script

    <?php
    $file = 'test.avif';
    $info = getimagesize($file);
    if ($info[2] === IMAGETYPE_HEIF) {
        // Check compatible brands manually
        $fh = fopen($file, 'rb');
        $header = fread($fh, 128);
        fclose($fh);
        if (strpos($header, 'avif') !== false) {
            $info[2] = IMAGETYPE_AVIF;
        }
    }
    
    var_dump($info[2]); // return 19 - Expected IMAGETYPE_AVIF, got IMAGETYPE_HEIF
  4. changed the title [-]AVIF images misdetected as HEIF after introducing HEIF support in GD[/-] [+]AVIF images misdetected as HEIF after introducing HEIF support in getimagesize()[/+] on Oct 18, 2025
  5. ndossche commented on Oct 18, 2025

    @ndossche
    Member

    There's also the "stupid but simple" way to fix this:

    diff --git a/ext/standard/image.c b/ext/standard/image.c
    index 97dcc437c83..4eadace55ec 100644
    --- a/ext/standard/image.c
    +++ b/ext/standard/image.c
    @@ -1435,15 +1435,16 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp
     		return IMAGE_FILETYPE_JP2;
     	}
     
    +	if (!php_stream_rewind(stream) && php_is_image_avif(stream)) {
    +		return IMAGE_FILETYPE_AVIF;
    +	}
    +
    +	/* See GH-20201: this needs to be after avif checks to avoid identifying avif as heif. */
     	if (twelve_bytes_read && !memcmp(filetype + 4, php_sig_ftyp, 4) &&
     		(!memcmp(filetype + 8, php_sig_mif1, 4) || !memcmp(filetype + 8, php_sig_heic, 4) || !memcmp(filetype + 8, php_sig_heix, 4))) {
     		return IMAGE_FILETYPE_HEIF;
     	}
     
    -	if (!php_stream_rewind(stream) && php_is_image_avif(stream)) {
    -		return IMAGE_FILETYPE_AVIF;
    -	}
    -
     /* AFTER ALL ABOVE FAILED */
     	if (php_get_wbmp(stream, NULL, 1)) {
     		return IMAGE_FILETYPE_WBMP;
    
  6. ndossche commented on Oct 18, 2025

    @ndossche
    Member

    @andypost What is the license of that test image? I'm asking so I know if we are allowed to check it into the php-src repo.

  7. andypost commented on Oct 19, 2025

    @andypost
    ContributorAuthor

    I asked community about license and as it's a part of core and is not exposed as images in demo sites it should be gpl2+ so could be reused, demo images are bundled using CC share-alike 2

    Originally it was added in https://www.drupal.org/project/drupal/issues/3202016 using imagick from png file

  8. ndossche commented on Oct 19, 2025

    @ndossche
    Member

    I see. Thanks for getting back to me.
    I don't believe we can embed GPL stuff in PHP. However, based on your description, I managed to craft my own reproducer image (with a little help of a hex editor to override ftyp).

  9. added a commit that references this issue on Oct 19, 2025
    472b778
  10. catch56 commented on Oct 20, 2025

    @catch56

    I went back to the original issue that added the images, it was https://www.drupal.org/node/373613 in 2009. @quicksketch created the images for that issue, so this means they're GPL and e.g. weren't originally elsewhere with a different license.

    @quicksketch is still around and we could ask him to dual-license the images as something else for PHP (IANAL etc. but I'm guessing something like that would be enough). But if you're able to create your own versions that might be quicker.

  11. quicksketch commented on Oct 20, 2025

    @quicksketch

    As the sole author of that original image, I would be more than happy to re-license / dual license. I don't think there is any embedded license information. But I give my full permission. LMK if you need anything from me.

  12. ndossche commented on Oct 20, 2025

    @ndossche
    Member

    Thanks for jumping in! In the meantime I had already managed to construct a reproducer based on the descriptions given. I'll keep in mind for the future who to contact if we ever need to check in a sample reproducer. Thanks!

  13. added 2 commits that reference this issue on Oct 29, 2025
    6cf45c4
    0b974dd
  14. andypost commented on Oct 31, 2025

    @andypost
    ContributorAuthor

    Thank you! Now tests passed and only image interpolation tests needs tuning for the new release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions