From cee33bab16b1fd2c7a9101c46d4bae30f1233ce9 Mon Sep 17 00:00:00 2001 From: Ben Morss Date: Mon, 5 Jul 2021 17:19:51 +0200 Subject: [PATCH] AVIF support for getimagesize() and imagecreatefromstring() Thanks to Joe Drago for help with the AVIF detection code. Co-authored-by: Nikita Popov Co-authored-by: Christoph M. Becker Closes GH-7091. --- ext/gd/gd.c | 69 ++++++----- ext/gd/libgd/gd.h | 1 - ext/gd/php_gd.h | 3 + ext/gd/tests/imagecreatefromstring_avif.phpt | 29 +++++ ...magecreatefromstring_compatible_brand.avif | Bin 0 -> 9717 bytes .../imagecreatefromstring_major_brand.avif | Bin 0 -> 6872 bytes ext/standard/image.c | 113 +++++++++++++++++- ext/standard/php_image.h | 3 + ext/standard/tests/image/getimagesize.phpt | 15 ++- .../tests/image/image_type_to_extension.phpt | 6 +- .../tests/image/image_type_to_mime_type.phpt | 4 +- .../image_type_to_mime_type_variation3.phpt | 3 + ext/standard/tests/image/test1pix.avif | Bin 0 -> 1284 bytes 13 files changed, 208 insertions(+), 38 deletions(-) create mode 100644 ext/gd/tests/imagecreatefromstring_avif.phpt create mode 100644 ext/gd/tests/imagecreatefromstring_compatible_brand.avif create mode 100644 ext/gd/tests/imagecreatefromstring_major_brand.avif create mode 100644 ext/standard/tests/image/test1pix.avif diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 08974023a65..f7723e166fb 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -31,8 +31,10 @@ #include #include "SAPI.h" #include "php_gd.h" +#include "ext/standard/php_image.h" #include "ext/standard/info.h" #include "php_open_temporary_file.h" +#include "php_memory_streams.h" #include "zend_object_handlers.h" #include "zend_interfaces.h" @@ -145,7 +147,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char static gdIOCtx *create_stream_context_from_zval(zval *to_zval); static gdIOCtx *create_stream_context(php_stream *stream, int close_stream); static gdIOCtx *create_output_context(void); -static int _php_image_type(char data[12]); +static int _php_image_type(zend_string *data); /* output streaming (formerly gd_ctx.c) */ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()); @@ -1469,42 +1471,54 @@ static int _php_ctx_getmbi(gdIOCtx *ctx) } /* }}} */ -/* {{{ _php_image_type */ +/* {{{ _php_image_type + * Based on ext/standard/image.c + */ static const char php_sig_gd2[3] = {'g', 'd', '2'}; -static int _php_image_type (char data[12]) +static int _php_image_type(zend_string *data) { - /* Based on ext/standard/image.c */ - - if (data == NULL) { + if (ZSTR_LEN(data) < 12) { + /* Handle this the same way as an unknown image type. */ return -1; } - if (!memcmp(data, php_sig_gd2, sizeof(php_sig_gd2))) { + if (!memcmp(ZSTR_VAL(data), php_sig_gd2, sizeof(php_sig_gd2))) { return PHP_GDIMG_TYPE_GD2; - } else if (!memcmp(data, php_sig_jpg, sizeof(php_sig_jpg))) { + } else if (!memcmp(ZSTR_VAL(data), php_sig_jpg, sizeof(php_sig_jpg))) { return PHP_GDIMG_TYPE_JPG; - } else if (!memcmp(data, php_sig_png, sizeof(php_sig_png))) { + } else if (!memcmp(ZSTR_VAL(data), php_sig_png, sizeof(php_sig_png))) { return PHP_GDIMG_TYPE_PNG; - } else if (!memcmp(data, php_sig_gif, sizeof(php_sig_gif))) { + } else if (!memcmp(ZSTR_VAL(data), php_sig_gif, sizeof(php_sig_gif))) { return PHP_GDIMG_TYPE_GIF; - } else if (!memcmp(data, php_sig_bmp, sizeof(php_sig_bmp))) { + } else if (!memcmp(ZSTR_VAL(data), php_sig_bmp, sizeof(php_sig_bmp))) { return PHP_GDIMG_TYPE_BMP; - } else if(!memcmp(data, php_sig_riff, sizeof(php_sig_riff)) && !memcmp(data + sizeof(php_sig_riff) + sizeof(uint32_t), php_sig_webp, sizeof(php_sig_webp))) { + } else if(!memcmp(ZSTR_VAL(data), php_sig_riff, sizeof(php_sig_riff)) && !memcmp(ZSTR_VAL(data) + sizeof(php_sig_riff) + sizeof(uint32_t), php_sig_webp, sizeof(php_sig_webp))) { return PHP_GDIMG_TYPE_WEBP; } - else { - gdIOCtx *io_ctx; - io_ctx = gdNewDynamicCtxEx(8, data, 0); - if (io_ctx) { - if (_php_ctx_getmbi(io_ctx) == 0 && _php_ctx_getmbi(io_ctx) >= 0) { - io_ctx->gd_free(io_ctx); - return PHP_GDIMG_TYPE_WBM; - } else { - io_ctx->gd_free(io_ctx); - } + + php_stream *image_stream = php_stream_memory_open(TEMP_STREAM_READONLY, data); + + if (image_stream != NULL) { + bool is_avif = php_is_image_avif(image_stream); + php_stream_close(image_stream); + + if (is_avif) { + return PHP_GDIMG_TYPE_AVIF; } } + + gdIOCtx *io_ctx; + io_ctx = gdNewDynamicCtxEx(8, ZSTR_VAL(data), 0); + if (io_ctx) { + if (_php_ctx_getmbi(io_ctx) == 0 && _php_ctx_getmbi(io_ctx) >= 0) { + io_ctx->gd_free(io_ctx); + return PHP_GDIMG_TYPE_WBM; + } else { + io_ctx->gd_free(io_ctx); + } + } + return -1; } /* }}} */ @@ -1540,21 +1554,12 @@ PHP_FUNCTION(imagecreatefromstring) zend_string *data; gdImagePtr im; int imtype; - char sig[12]; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &data) == FAILURE) { RETURN_THROWS(); } - if (ZSTR_LEN(data) < sizeof(sig)) { - /* Handle this the same way as an unknown image type. */ - php_error_docref(NULL, E_WARNING, "Data is not in a recognized format"); - RETURN_FALSE; - } - - memcpy(sig, ZSTR_VAL(data), sizeof(sig)); - - imtype = _php_image_type(sig); + imtype = _php_image_type(data); switch (imtype) { case PHP_GDIMG_TYPE_JPG: diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index 163254f75f3..51235c7c1d6 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -628,7 +628,6 @@ gdImagePtr gdImageCreateFromGif(FILE *fd); gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in); gdImagePtr gdImageCreateFromGifSource(gdSourcePtr in); -//TODO: we may not need all of these void gdImageAvif(gdImagePtr im, FILE *outfile); void gdImageAvifEx(gdImagePtr im, FILE *outfile, int quality, int speed); void *gdImageAvifPtr(gdImagePtr im, int *size); diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h index e804e748d2e..f063f30e3e0 100644 --- a/ext/gd/php_gd.h +++ b/ext/gd/php_gd.h @@ -18,6 +18,9 @@ #ifndef PHP_GD_H #define PHP_GD_H +#include "zend_string.h" +#include "php_streams.h" + #if defined(HAVE_LIBGD) || defined(HAVE_GD_BUNDLED) /* open_basedir and safe_mode checks */ diff --git a/ext/gd/tests/imagecreatefromstring_avif.phpt b/ext/gd/tests/imagecreatefromstring_avif.phpt new file mode 100644 index 00000000000..3af75344912 --- /dev/null +++ b/ext/gd/tests/imagecreatefromstring_avif.phpt @@ -0,0 +1,29 @@ +--TEST-- +imagecreatefromstring() - AVIF format +--EXTENSIONS-- +gd +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Reading image whose major brand is 'avif': +int(250) +int(375) +Reading image with a compatible brand that's 'avif': +int(480) +int(270) diff --git a/ext/gd/tests/imagecreatefromstring_compatible_brand.avif b/ext/gd/tests/imagecreatefromstring_compatible_brand.avif new file mode 100644 index 0000000000000000000000000000000000000000..4039547d57413457c9b3c6573e9a42b378e00a41 GIT binary patch literal 9717 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

Sh@MyxRQd~_ba6|+ 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 YcWHekFfHtD48Qn4e7zDRI7HC@03D=sOaK4? literal 0 HcmV?d00001 diff --git a/ext/gd/tests/imagecreatefromstring_major_brand.avif b/ext/gd/tests/imagecreatefromstring_major_brand.avif new file mode 100644 index 0000000000000000000000000000000000000000..1c79a8e91ba7df18ec2de2a890f2990b046b7acd GIT binary patch literal 6872 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 G>Hh(yju2b` literal 0 HcmV?d00001 diff --git a/ext/standard/image.c b/ext/standard/image.c index 218476599a6..d2e4fec4054 100644 --- a/ext/standard/image.c +++ b/ext/standard/image.c @@ -87,7 +87,8 @@ PHP_MINIT_FUNCTION(imagetypes) REGISTER_LONG_CONSTANT("IMAGETYPE_JPEG2000",IMAGE_FILETYPE_JPC, CONST_CS | CONST_PERSISTENT); /* keep alias */ REGISTER_LONG_CONSTANT("IMAGETYPE_XBM", IMAGE_FILETYPE_XBM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_ICO", IMAGE_FILETYPE_ICO, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_WEBP", IMAGE_FILETYPE_WEBP, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_AVIF", IMAGE_FILETYPE_AVIF, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_UNKNOWN", IMAGE_FILETYPE_UNKNOWN, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMAGETYPE_COUNT", IMAGE_FILETYPE_COUNT, CONST_CS | CONST_PERSISTENT); return SUCCESS; @@ -1148,6 +1149,99 @@ static struct gfxinfo *php_handle_webp(php_stream * stream) } /* }}} */ +/* {{{ php_handle_avif + * There's no simple way to get this information - so, for now, this is unsupported. + * Simply return 0 for everything. + */ +static struct gfxinfo *php_handle_avif(php_stream * stream) { + return ecalloc(1, sizeof(struct gfxinfo)); +} +/* }}} */ + +/* {{{ php_ntohl + * Convert a big-endian network uint32 to host order - + * which may be either little-endian or big-endian. + * Thanks to Rob Pike via Joe Drago: + * https://commandcenter.blogspot.nl/2012/04/byte-order-fallacy.html + */ +static uint32_t php_ntohl(uint32_t val) { + uint8_t data[4]; + + memcpy(&data, &val, sizeof(data)); + return ((uint32_t)data[3] << 0) | + ((uint32_t)data[2] << 8) | + ((uint32_t)data[1] << 16) | + ((uint32_t)data[0] << 24); +} +/* }}} */ + +/* {{{ php_is_image_avif + * detect whether an image is of type AVIF + * + * An AVIF image will start off a header "box". + * This starts with with a four-byte integer containing the number of bytes in the filetype box. + * This must be followed by the string "ftyp". + * Next comes a four-byte string indicating the "major brand". + * If that's "avif" or "avis", this is an AVIF image. + * Next, there's a four-byte "minor version" field, which we can ignore. + * Next comes an array of four-byte strings containing "compatible brands". + * These extend to the end of the box. + * If any of the compatible brands is "avif" or "avis", then this is an AVIF image. + * Otherwise, well, it's not. + * For more, see https://mpeg.chiariglione.org/standards/mpeg-4/iso-base-media-file-format/text-isoiec-14496-12-5th-edition + */ +bool php_is_image_avif(php_stream * stream) { + uint32_t header_size_reversed, header_size, i; + char box_type[4], brand[4]; + + ZEND_ASSERT(stream != NULL); + + if (php_stream_read(stream, (char *) &header_size_reversed, 4) != 4) { + return 0; + } + + header_size = php_ntohl(header_size_reversed); + + /* If the box type isn't "ftyp", it can't be an AVIF image. */ + if (php_stream_read(stream, box_type, 4) != 4) { + return 0; + } + + if (memcmp(box_type, "ftyp", 4)) { + return 0; + } + + /* If the major brand is "avif" or "avis", it's an AVIF image. */ + if (php_stream_read(stream, brand, 4) != 4) { + return 0; + } + + if (!memcmp(brand, "avif", 4) || !memcmp(brand, "avis", 4)) { + return 1; + } + + /* Skip the next four bytes, which are the "minor version". */ + if (php_stream_read(stream, brand, 4) != 4) { + return 0; + } + + /* Look for "avif" or "avis" in any member of compatible_brands[], to the end of the header. + Note we've already read four groups of four bytes. */ + + for (i = 16; i < header_size; i += 4) { + if (php_stream_read(stream, brand, 4) != 4) { + return 0; + } + + if (!memcmp(brand, "avif", 4) || !memcmp(brand, "avis", 4)) { + return 1; + } + } + + return 0; +} +/* }}} */ + /* {{{ php_image_type_to_mime_type * Convert internal image_type to mime type */ PHPAPI char * php_image_type_to_mime_type(int image_type) @@ -1183,6 +1277,8 @@ PHPAPI char * php_image_type_to_mime_type(int image_type) return "image/vnd.microsoft.icon"; case IMAGE_FILETYPE_WEBP: return "image/webp"; + case IMAGE_FILETYPE_AVIF: + return "image/avif"; default: case IMAGE_FILETYPE_UNKNOWN: return "application/octet-stream"; /* suppose binary format */ @@ -1265,6 +1361,9 @@ PHP_FUNCTION(image_type_to_extension) case IMAGE_FILETYPE_WEBP: imgext = ".webp"; break; + case IMAGE_FILETYPE_AVIF: + imgext = ".avif"; + break; } if (imgext) { @@ -1277,7 +1376,7 @@ PHP_FUNCTION(image_type_to_extension) /* {{{ php_imagetype detect filetype from first bytes */ -PHPAPI int php_getimagetype(php_stream * stream, const char *input, char *filetype) +PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetype) { char tmp[12]; int twelve_bytes_read; @@ -1349,17 +1448,24 @@ PHPAPI int php_getimagetype(php_stream * stream, const char *input, char *filety return IMAGE_FILETYPE_JP2; } + 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; } + if (!twelve_bytes_read) { php_error_docref(NULL, E_NOTICE, "Error reading from %s!", input); return IMAGE_FILETYPE_UNKNOWN; } + if (php_get_xbm(stream, NULL)) { return IMAGE_FILETYPE_XBM; } + return IMAGE_FILETYPE_UNKNOWN; } /* }}} */ @@ -1431,6 +1537,9 @@ static void php_getimagesize_from_stream(php_stream *stream, char *input, zval * case IMAGE_FILETYPE_WEBP: result = php_handle_webp(stream); break; + case IMAGE_FILETYPE_AVIF: + result = php_handle_avif(stream); + break; default: case IMAGE_FILETYPE_UNKNOWN: break; diff --git a/ext/standard/php_image.h b/ext/standard/php_image.h index 8311f4b2ab8..b975e0bf147 100644 --- a/ext/standard/php_image.h +++ b/ext/standard/php_image.h @@ -43,6 +43,7 @@ typedef enum IMAGE_FILETYPE_XBM, IMAGE_FILETYPE_ICO, IMAGE_FILETYPE_WEBP, + IMAGE_FILETYPE_AVIF, /* WHEN EXTENDING: PLEASE ALSO REGISTER IN image.c:PHP_MINIT_FUNCTION(imagetypes) */ IMAGE_FILETYPE_COUNT } image_filetype; @@ -54,4 +55,6 @@ PHPAPI int php_getimagetype(php_stream *stream, const char *input, char *filetyp PHPAPI char * php_image_type_to_mime_type(int image_type); +PHPAPI bool php_is_image_avif(php_stream *stream); + #endif /* PHP_IMAGE_H */ diff --git a/ext/standard/tests/image/getimagesize.phpt b/ext/standard/tests/image/getimagesize.phpt index 582959f3ae6..0a1002d2934 100644 --- a/ext/standard/tests/image/getimagesize.phpt +++ b/ext/standard/tests/image/getimagesize.phpt @@ -23,7 +23,7 @@ GetImageSize() var_dump($result); ?> --EXPECT-- -array(16) { +array(17) { ["test-1pix.bmp"]=> array(6) { [0]=> @@ -69,6 +69,19 @@ array(16) { ["mime"]=> string(9) "image/bmp" } + ["test1pix.avif"]=> + array(5) { + [0]=> + int(0) + [1]=> + int(0) + [2]=> + int(19) + [3]=> + string(20) "width="0" height="0"" + ["mime"]=> + string(10) "image/avif" + } ["test1pix.bmp"]=> array(6) { [0]=> diff --git a/ext/standard/tests/image/image_type_to_extension.phpt b/ext/standard/tests/image/image_type_to_extension.phpt index fd60fc454e1..9b0d991d070 100644 --- a/ext/standard/tests/image/image_type_to_extension.phpt +++ b/ext/standard/tests/image/image_type_to_extension.phpt @@ -23,7 +23,8 @@ image_type_to_extension() "IMAGETYPE_WBMP" => IMAGETYPE_WBMP, "IMAGETYPE_JPEG2000" => IMAGETYPE_JPEG2000, "IMAGETYPE_XBM" => IMAGETYPE_XBM, - "IMAGETYPE_WEBP" => IMAGETYPE_WEBP + "IMAGETYPE_WEBP" => IMAGETYPE_WEBP, + "IMAGETYPE_AVIF" => IMAGETYPE_AVIF, ); foreach($constants as $name => $constant) { printf("Constant: %s\n\tWith dot: %s\n\tWithout dot: %s\n", $name, image_type_to_extension($constant), image_type_to_extension($constant, false)); @@ -85,6 +86,9 @@ Constant: IMAGETYPE_XBM Constant: IMAGETYPE_WEBP With dot: .webp Without dot: webp +Constant: IMAGETYPE_AVIF + With dot: .avif + Without dot: avif bool(false) bool(false) Done diff --git a/ext/standard/tests/image/image_type_to_mime_type.phpt b/ext/standard/tests/image/image_type_to_mime_type.phpt index b4f6d3c403f..5877efe531f 100644 --- a/ext/standard/tests/image/image_type_to_mime_type.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type.phpt @@ -24,13 +24,15 @@ image_type_to_mime_type() var_dump($result); ?> --EXPECT-- -array(16) { +array(17) { ["test-1pix.bmp"]=> string(9) "image/bmp" ["test12pix.webp"]=> string(10) "image/webp" ["test1bpix.bmp"]=> string(9) "image/bmp" + ["test1pix.avif"]=> + string(10) "image/avif" ["test1pix.bmp"]=> string(9) "image/bmp" ["test1pix.jp2"]=> diff --git a/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt b/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt index 49a53c468b1..fc17cb5ecd9 100644 --- a/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt +++ b/ext/standard/tests/image/image_type_to_mime_type_variation3.phpt @@ -72,4 +72,7 @@ string\(24\) "image\/vnd.microsoft.icon" string\(10\) "image\/webp" -- Iteration 19 -- +string\(10\) "image\/avif" + +-- Iteration 20 -- string\(24\) "application\/octet-stream" diff --git a/ext/standard/tests/image/test1pix.avif b/ext/standard/tests/image/test1pix.avif new file mode 100644 index 0000000000000000000000000000000000000000..3684f22afdfda80d22d5b8b420d68d1ec23254c9 GIT binary patch literal 1284 zcmZQzU{FXasVqn=%S>Yc0uY^>nP!-qnV9D5Xz0Yiz_>6swImTF2Lu`!DLF+DCIdr3 zW^xIP4We^0lVHa16=as=g5?;2q)ui|elm#X!oa}901^RW#>Wf{%!)uhgm)51O98P{ zW@aAPC14pTASV^11f(Oe%)rn&KPMmT0E7%s8YJVGQ;?AeQYn>LlnOC{fq^fvv?2#= zC&_ zxY#5lH~q*BFyeEW0CX6G1JkrH;Vq>JKp9SuOim*svy;(8HX#R=UV(>>j~W?nFj-za zuFG=P_)YLb{#WKlj&+DHI%i@s{k`#mJQ>lvXNAoFCQV>+XO}*DC$_`u)@r4+G%uY9 zF*}+2i)Lq)-2C!}c}MI-HuotC7TITx%$?12aE3UC_`?^IR?nSXs#w^3zWvvft_n!*_mp>Pi{po9<>)!ZeTEILRdOPTAV8^Q=3=vuMFdjpx?8)Ba8OzZbu->Gf$<;SGx;pBwF~<5DeqBCL7-bHtL1 z+^@Mdu=M(wtqzgpRAD(~@yzw4(e~DxI*j#x3 zudTKuOp4d~(DI|ZmwdGRGhw61v8EUQTRxiUPRK2oVwB|0|21DZt#U7Y?x{?gDwYFZ6<=V1( z=bOrnr-dYnrBmE)zMCX?NaeV~4UHL=T?=PU+`5DDSa)YWtA^gr^$HeG5-(evnE1A@ zqJ_KQu4q?m?1|mR(=1;zetWm*9J_14(Gbpu3l~K%Ic2U{{QT7A3!y`&8ur;shH)~ua|@wXt481%+>2?vfsuT=Na?gj&%Xs3eS$oV$YJL%k89s zj_YwG{Lf_Z_)$4AdQQva+VB4Q3iq}~sg{MuH=I{FFZSZ?(s#+9`H#+Nh_hI&+H&u7 z>g8{