diff --git a/dgif_lib.c b/dgif_lib.c index 82fc097..214a0e7 100644 --- a/dgif_lib.c +++ b/dgif_lib.c @@ -810,7 +810,8 @@ DGifSetupDecompress(GifFileType *GifFile) /* coverity[check_return] */ if (InternalRead(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */ - return GIF_ERROR; /* Failed to read Code size. */ + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; /* Failed to read Code size. */ } BitsPerPixel = CodeSize; @@ -1118,6 +1119,31 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) return GIF_OK; } +/****************************************************************************** + This routine is called in case of error during parsing image. We need to + decrease image counter and reallocate memory for saved images. Not decreasing + ImageCount may lead to null pointer dereference, because the last element in + SavedImages may point to the spoilt image and null pointer buffers. +*******************************************************************************/ +void +DGifDecreaseImageCounter(GifFileType *GifFile) +{ + GifFile->ImageCount--; + if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) { + free(GifFile->SavedImages[GifFile->ImageCount].RasterBits); + } + if (GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap != NULL) { + GifFreeMapObject(GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap); + } + + // Realloc array according to the new image counter. + SavedImage *correct_saved_images = (SavedImage *)reallocarray( + GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage)); + if (correct_saved_images != NULL) { + GifFile->SavedImages = correct_saved_images; + } +} + /****************************************************************************** This routine reads an entire GIF into core, hanging all its state info off the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() @@ -1148,17 +1174,20 @@ DGifSlurp(GifFileType *GifFile) /* Allocate memory for the image */ if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 || sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { + DGifDecreaseImageCounter(GifFile); return GIF_ERROR; } ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { + DGifDecreaseImageCounter(GifFile); return GIF_ERROR; } sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize, sizeof(GifPixelType)); if (sp->RasterBits == NULL) { + DGifDecreaseImageCounter(GifFile); return GIF_ERROR; } @@ -1177,13 +1206,17 @@ DGifSlurp(GifFileType *GifFile) j += InterlacedJumps[i]) { if (DGifGetLine(GifFile, sp->RasterBits+j*sp->ImageDesc.Width, - sp->ImageDesc.Width) == GIF_ERROR) - return GIF_ERROR; + sp->ImageDesc.Width) == GIF_ERROR) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } } } else { - if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) - return (GIF_ERROR); + if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } } if (GifFile->ExtensionBlocks) {