Closed
Description
Version: ImageMagick 7.0.6-1 Q16 x86_64
$magick identify $FILE
When identify JNG file that contains chunk data, imagemagick will allocate memory to store the chunk data in function ReadOneJNGImage
Here is the critical code:
if (length != 0)
{
chunk=(unsigned char *) AcquireQuantumMemory(length,sizeof(*chunk)); //length can be controlled
if (chunk == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
for (i=0; i < (ssize_t) length; i++)
{
int
c;
c=ReadBlobByte(image);
if (c == EOF)
break;
chunk[i]=(unsigned char) c;
}
p=chunk;
}
length can be controlled as follow:
length=ReadBlobMSBLong(image); //length is from file data
count=(unsigned int) ReadBlob(image,4,(unsigned char *) type);
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading JNG chunk type %c%c%c%c, length: %.20g",
type[0],type[1],type[2],type[3],(double) length);
if (length > PNG_UINT_31_MAX || count == 0)
ThrowReaderException(CorruptImageError,"CorruptImage");
So the only limitation is it must smaller than PNG_UINT_31_MAX, it is still very large.
Also when chunk type is JDAT, it will write chunk data to file as follow:
if (memcmp(type,mng_JDAT,4) == 0)
{
/* Copy chunk to color_image->blob */
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Copying JDAT chunk data to color_blob.");
if (length != 0)
{
(void) WriteBlob(color_image,length,chunk); //write very large chunk data to file
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
}
continue;
}
So a crafted jng file can cause memory exhausted and large I/O.
testcase:
https://github.com/jgj212/poc/blob/master/mem-jng
Credit: ADLab of Venustech