From b817a4f71870a21e5cea844d397f21e54f8926d5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 14 Oct 2024 11:35:13 +0200 Subject: [PATCH] Fix GH-16427: Unchecked libavif return values Prior to libavif 1.1.0, `avifAlloc()` was infallible (it called `abort()` on OOM conditions); thus, several API functions which used `avifAlloc()` did not report failure. That changed as of libavif 1.0.0[1], so checking and handling failure conditions can now be done. However, due to `avifAlloc()` being fallible as of libavif 1.1.0, this error checking and handling is mandatory to avoid more serious issues. [1] Closes GH-16434. --- NEWS | 1 + ext/gd/libgd/gd_avif.c | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 4b7b0cd0fa1..bceee09997c 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ PHP NEWS - GD: . Fixed bug GH-16334 (imageaffine overflow on matrix elements). (David Carlier) + . Fixed bug GH-16427 (Unchecked libavif return values). (cmb) - GMP: . Fixed floating point exception bug with gmp_pow when using diff --git a/ext/gd/libgd/gd_avif.c b/ext/gd/libgd/gd_avif.c index 30075d2a899..9c1ffdc34bc 100644 --- a/ext/gd/libgd/gd_avif.c +++ b/ext/gd/libgd/gd_avif.c @@ -393,7 +393,13 @@ gdImagePtr gdImageCreateFromAvifCtx (gdIOCtx *ctx) // (While AVIF image pixel depth can be 8, 10, or 12 bits, GD truecolor images are 8-bit.) avifRGBImageSetDefaults(&rgb, decoder->image); rgb.depth = 8; +#if AVIF_VERSION >= 1000000 + result = avifRGBImageAllocatePixels(&rgb); + if (isAvifError(result, "Allocating RGB pixels failed")) + goto cleanup; +#else avifRGBImageAllocatePixels(&rgb); +#endif result = avifImageYUVToRGB(decoder->image, &rgb); if (isAvifError(result, "Conversion from YUV to RGB failed")) @@ -522,14 +528,25 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed) // Note that MATRIX_COEFFICIENTS_IDENTITY enables lossless conversion from RGB to YUV. avifImage *avifIm = avifImageCreate(gdImageSX(im), gdImageSY(im), 8, subsampling); - +#if AVIF_VERSION >= 1000000 + if (avifIm == NULL) { + gd_error("avif error - Creating image failed\n"); + goto cleanup; + } +#endif avifIm->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709; avifIm->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB; avifIm->matrixCoefficients = lossless ? AVIF_MATRIX_COEFFICIENTS_IDENTITY : AVIF_MATRIX_COEFFICIENTS_BT709; avifRGBImageSetDefaults(&rgb, avifIm); // this allocates memory, and sets rgb.rowBytes and rgb.pixels. +#if AVIF_VERSION >= 1000000 + result = avifRGBImageAllocatePixels(&rgb); + if (isAvifError(result, "Allocating RGB pixels failed")) + goto cleanup; +#else avifRGBImageAllocatePixels(&rgb); +#endif // Parse RGB data from the GD image, and copy it into the AVIF RGB image. // Convert 7-bit GD alpha channel values to 8-bit AVIF values. @@ -555,6 +572,12 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed) // Encode the image in AVIF format. encoder = avifEncoderCreate(); +#if AVIF_VERSION >= 1000000 + if (encoder == NULL) { + gd_error("avif error - Creating encoder failed\n"); + goto cleanup; + } +#endif int quantizerQuality = quality == QUALITY_DEFAULT ? QUANTIZER_DEFAULT : quality2Quantizer(quality);