Subject: | SEGV when Thumbnail() with animation gif. |
hello.
My friend found a bug.
He is so shy. then I report it.
perl get SEGV when Thumbnail() with animation gif.
Mogirfy() in PerlMagick/Magick.xs release memory of 'next'.
next->next is saved to image->next for future use.
but next->previous is not saved. and image->previous is not
initialized(NULL or garbage).
ThumbnailImage() in magick/resize.c call GetImageListLength() at end of
function.
GetImageListLength in magick/list.c use images->previous.
image->previous is not initialized.
Perl access garbage as a poiter and cought SEGV.
brief source code is here.
================================================================
= PerlMagick/Magick.xs
================================================================
void
Mogrify(ref,...)
PPCODE:
{
for (next=image; next; next=next->next)
{
image=next;
switch (ix)
{
case 83: /* Thumbnail */
{
image=ThumbnailImage(image,geometry.width,geometry.height,exception);
break;
}
}
if (image != (Image *) NULL)
{
if (next && (next != image))
{
image->next=next->next;
DeleteImageFromRegistry(*pv,next);
}
next=image;
}
}
}
================================================================
= magick/resize.c
================================================================
MagickExport Image *ThumbnailImage(const Image *image,const size_t
columns,
const size_t rows,ExceptionInfo *exception)
{
/* snip */
(void) FormatMagickString(value,MaxTextExtent,"%.20g",(double)
GetImageListLength(image));
return(thumbnail_image);
}
================================================================
= magic/list.c
================================================================
register ssize_t
i;
if (images == (const Image *) NULL)
return(-1);
assert(images->signature == MagickSignature);
for (i=0; images->previous != (Image *) NULL; i++)
images=images->previous;
return(i);
================================================================
I think previous should be saved.
================================================================
if (image != (Image *) NULL)
{
if (next && (next != image))
{
image->next=next->next;
if(next->next){
next->next-previous = image;
}
DeleteImageFromRegistry(*pv,next);
}
next=image;
}
}
================================================================
sorry my english is very broken.
best regard.