33
44#include "avif/internal.h"
55
6+ #include <limits.h>
7+ #include <stdint.h>
68#include <string.h>
79
810#define STR_HELPER (x ) #x
@@ -163,7 +165,7 @@ static void avifImageCopyNoAlloc(avifImage * dstImage, const avifImage * srcImag
163165 dstImage -> imir = srcImage -> imir ;
164166}
165167
166- void avifImageCopy (avifImage * dstImage , const avifImage * srcImage , avifPlanesFlags planes )
168+ avifResult avifImageCopy (avifImage * dstImage , const avifImage * srcImage , avifPlanesFlags planes )
167169{
168170 avifImageFreePlanes (dstImage , AVIF_PLANES_ALL );
169171 avifImageCopyNoAlloc (dstImage , srcImage );
@@ -174,7 +176,10 @@ void avifImageCopy(avifImage * dstImage, const avifImage * srcImage, avifPlanesF
174176 avifImageSetMetadataXMP (dstImage , srcImage -> xmp .data , srcImage -> xmp .size );
175177
176178 if ((planes & AVIF_PLANES_YUV ) && srcImage -> yuvPlanes [AVIF_CHAN_Y ]) {
177- avifImageAllocatePlanes (dstImage , AVIF_PLANES_YUV );
179+ const avifResult allocationResult = avifImageAllocatePlanes (dstImage , AVIF_PLANES_YUV );
180+ if (allocationResult != AVIF_RESULT_OK ) {
181+ return allocationResult ;
182+ }
178183
179184 avifPixelFormatInfo formatInfo ;
180185 avifGetPixelFormatInfo (srcImage -> yuvFormat , & formatInfo );
@@ -200,13 +205,17 @@ void avifImageCopy(avifImage * dstImage, const avifImage * srcImage, avifPlanesF
200205 }
201206
202207 if ((planes & AVIF_PLANES_A ) && srcImage -> alphaPlane ) {
203- avifImageAllocatePlanes (dstImage , AVIF_PLANES_A );
208+ const avifResult allocationResult = avifImageAllocatePlanes (dstImage , AVIF_PLANES_A );
209+ if (allocationResult != AVIF_RESULT_OK ) {
210+ return allocationResult ;
211+ }
204212 for (uint32_t j = 0 ; j < dstImage -> height ; ++ j ) {
205213 uint8_t * srcAlphaRow = & srcImage -> alphaPlane [j * srcImage -> alphaRowBytes ];
206214 uint8_t * dstAlphaRow = & dstImage -> alphaPlane [j * dstImage -> alphaRowBytes ];
207215 memcpy (dstAlphaRow , srcAlphaRow , dstImage -> alphaRowBytes );
208216 }
209217 }
218+ return AVIF_RESULT_OK ;
210219}
211220
212221avifResult avifImageSetViewRect (avifImage * dstImage , const avifImage * srcImage , const avifCropRect * rect )
@@ -264,45 +273,70 @@ void avifImageSetMetadataXMP(avifImage * image, const uint8_t * xmp, size_t xmpS
264273 avifRWDataSet (& image -> xmp , xmp , xmpSize );
265274}
266275
267- void avifImageAllocatePlanes (avifImage * image , avifPlanesFlags planes )
276+ avifResult avifImageAllocatePlanes (avifImage * image , avifPlanesFlags planes )
268277{
269- int channelSize = avifImageUsesU16 (image ) ? 2 : 1 ;
270- int fullRowBytes = channelSize * image -> width ;
271- int fullSize = fullRowBytes * image -> height ;
278+ if (image -> width == 0 || image -> height == 0 ) {
279+ return AVIF_RESULT_INVALID_ARGUMENT ;
280+ }
281+ const size_t channelSize = avifImageUsesU16 (image ) ? 2 : 1 ;
282+ if (image -> width > SIZE_MAX / channelSize ) {
283+ return AVIF_RESULT_INVALID_ARGUMENT ;
284+ }
285+ const size_t fullRowBytes = channelSize * image -> width ;
286+ if ((fullRowBytes > UINT32_MAX ) || (image -> height > SIZE_MAX / fullRowBytes )) {
287+ return AVIF_RESULT_INVALID_ARGUMENT ;
288+ }
289+ const size_t fullSize = fullRowBytes * image -> height ;
290+
272291 if ((planes & AVIF_PLANES_YUV ) && (image -> yuvFormat != AVIF_PIXEL_FORMAT_NONE )) {
273292 avifPixelFormatInfo info ;
274293 avifGetPixelFormatInfo (image -> yuvFormat , & info );
275294
276- int shiftedW = (image -> width + info .chromaShiftX ) >> info .chromaShiftX ;
277- int shiftedH = (image -> height + info .chromaShiftY ) >> info .chromaShiftY ;
295+ // Intermediary computation as 64 bits in case width or height is exactly UINT32_MAX.
296+ const uint32_t shiftedW = (uint32_t )(((uint64_t )image -> width + info .chromaShiftX ) >> info .chromaShiftX );
297+ const uint32_t shiftedH = (uint32_t )(((uint64_t )image -> height + info .chromaShiftY ) >> info .chromaShiftY );
278298
279- int uvRowBytes = channelSize * shiftedW ;
280- int uvSize = uvRowBytes * shiftedH ;
299+ // These are less than or equal to fullRowBytes/fullSize. No need to check overflows.
300+ const size_t uvRowBytes = channelSize * shiftedW ;
301+ const size_t uvSize = uvRowBytes * shiftedH ;
281302
303+ image -> imageOwnsYUVPlanes = AVIF_TRUE ;
282304 if (!image -> yuvPlanes [AVIF_CHAN_Y ]) {
283305 image -> yuvRowBytes [AVIF_CHAN_Y ] = fullRowBytes ;
284306 image -> yuvPlanes [AVIF_CHAN_Y ] = avifAlloc (fullSize );
307+ if (!image -> yuvPlanes [AVIF_CHAN_Y ]) {
308+ return AVIF_RESULT_OUT_OF_MEMORY ;
309+ }
285310 }
286311
287312 if (image -> yuvFormat != AVIF_PIXEL_FORMAT_YUV400 ) {
288313 if (!image -> yuvPlanes [AVIF_CHAN_U ]) {
289314 image -> yuvRowBytes [AVIF_CHAN_U ] = uvRowBytes ;
290315 image -> yuvPlanes [AVIF_CHAN_U ] = avifAlloc (uvSize );
316+ if (!image -> yuvPlanes [AVIF_CHAN_U ]) {
317+ return AVIF_RESULT_OUT_OF_MEMORY ;
318+ }
291319 }
292320 if (!image -> yuvPlanes [AVIF_CHAN_V ]) {
293321 image -> yuvRowBytes [AVIF_CHAN_V ] = uvRowBytes ;
294322 image -> yuvPlanes [AVIF_CHAN_V ] = avifAlloc (uvSize );
323+ if (!image -> yuvPlanes [AVIF_CHAN_V ]) {
324+ return AVIF_RESULT_OUT_OF_MEMORY ;
325+ }
295326 }
296327 }
297- image -> imageOwnsYUVPlanes = AVIF_TRUE ;
298328 }
299329 if (planes & AVIF_PLANES_A ) {
330+ image -> imageOwnsAlphaPlane = AVIF_TRUE ;
300331 if (!image -> alphaPlane ) {
301332 image -> alphaRowBytes = fullRowBytes ;
302333 image -> alphaPlane = avifAlloc (fullSize );
334+ if (!image -> alphaPlane ) {
335+ return AVIF_RESULT_OUT_OF_MEMORY ;
336+ }
303337 }
304- image -> imageOwnsAlphaPlane = AVIF_TRUE ;
305338 }
339+ return AVIF_RESULT_OK ;
306340}
307341
308342void avifImageFreePlanes (avifImage * image , avifPlanesFlags planes )
0 commit comments