Description
Prerequisites
- I have written a descriptive issue title
- I have verified that I am using the latest version of ImageMagick
- I have searched open and closed issues to ensure it has not already been reported
Description
memory leak in WriteDIBImage in coders/dib.c
Steps to Reproduce
The critical code snippets are:
https://github.com/ImageMagick/ImageMagick/blob/master/coders/dib.c#L1330
if (dib_info.bits_per_pixel == 8) //line 1330
if (image_info->compression != NoCompression) //line 1331
{
size_t
length;
/*
Convert run-length encoded raster pixels.
*/
length=2UL*(bytes_per_line+2UL)+2UL;
dib_data=(unsigned char *) AcquireQuantumMemory(length, // line 1340
(image->rows+2UL)*sizeof(*dib_data));
if (dib_data == (unsigned char *) NULL)
{
pixels=(unsigned char *) RelinquishMagickMemory(pixels);
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
}
dib_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
pixels,dib_data);
pixels=(unsigned char *) RelinquishMagickMemory(pixels);
pixels=dib_data; // line 1350
dib_info.compression = BI_RLE8;
}and
https://github.com/ImageMagick/ImageMagick/blob/master/coders/dib.c#L1367
if (image->storage_class == PseudoClass) //line 1367
{
if (dib_info.bits_per_pixel <= 8) //line 1369
{
unsigned char
*dib_colormap;
/*
Dump colormap to file.
*/
dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
(1UL << dib_info.bits_per_pixel),4*sizeof(*dib_colormap));
if (dib_colormap == (unsigned char *) NULL) // line 1379
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); // line 1380
q=dib_colormap;According to the code in function WriteDIBImage before line 1330, when image->storage_class is not DirectClass (i.e. storage class is PseudoClass) and image_info->depth<=8, dib_info.bits_per_pixel can be equal to 8 (at line 1151-1155), as a result, dib_info.compression will be BI_RGB (at line 1164-1165). So the 4 conditions at line 1330, 1331, 1367 and 1369 can be satisfied at the same time in some setting.
When the 4 conditions are satisfied and dib_data is successfully allocated at line 1340, dib_data will be assigned to pixels at line 1350. However, when the allocation at line 1377 fails, the function don't free dib_data memory as done at line 1410 before returning with exception at line 1378. As a result, a memory leak will happen.
The size of leaked memory is 4*((image->columnsdib_info.bits_per_pixel+31)/32)(image->rows+2UL)*sizeof(*dib_data) = (image->columns + 4) * (image->rows + 2) * sizeof(*dib_data), which may be a large value. (ps. dib_info.bits_per_pixel is 8)
Patch Suggestion:
dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t) // line 1377
(1UL << dib_info.bits_per_pixel),4*sizeof(*dib_colormap));
if (dib_colormap == (unsigned char *) NULL)
{
pixels=(unsigned char *) RelinquishMagickMemory(pixels);
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
}
q=dib_colormap;System Configuration
- ImageMagick version: ImageMagick-4f0ea40e2a090e245f31d1f05247520d6e7eb4ca
- Environment (Operating system, version and so on): Ubuntu 16.04
- Additional information:
Credit to Bingchang Liu at VARAS of IIE