Package: libgif4 Version: 4.1.6-9 Severity: normal Tags: patch DGifSlurp ignores interlace flag and treat an interlaced image as a normal image.
-- System Information: Debian Release: wheezy/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 3.0.0 (SMP w/4 CPU cores) Locale: LANG=ja_JP.eucJP, LC_CTYPE=ja_JP.eucJP (charmap=EUC-JP) Shell: /bin/sh linked to /bin/dash Versions of packages libgif4 depends on: ii libc6 2.13-14 Embedded GNU C Library: Shared lib libgif4 recommends no packages. libgif4 suggests no packages. -- no debconf information
#include <gif_lib.h>
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
GifFileType *gif;
ColorMapObject *cmap;
XImage img;
int image_size, i;
XSetWindowAttributes attr;
Display *display;
Window window;
if (argc < 2)
{
return 0;
}
gif = DGifOpenFileName(argv[1]);
if (gif == NULL)
{
return 1;
}
if (DGifSlurp(gif) != GIF_OK)
{
return 1;
}
cmap = gif->SavedImages[0].ImageDesc.ColorMap;
if (cmap == NULL)
{
cmap = gif->SColorMap;
}
img.width = gif->SavedImages[0].ImageDesc.Width;
img.height = gif->SavedImages[0].ImageDesc.Height;
img.xoffset = 0;
img.format = ZPixmap;
img.byte_order = MSBFirst;
img.bitmap_unit = 8;
img.bitmap_pad = 8;
img.depth = 24;
img.bytes_per_line = 0;
img.bits_per_pixel = 24;
img.red_mask = 0xff0000;
img.green_mask = 0xff00;
img.blue_mask = 0xff;
if (!XInitImage(&img))
{
return 1;
}
image_size = img.width * img.height;
img.data = malloc(3 * image_size);
if (img.data == NULL)
{
return 1;
}
for (i = 0; i < image_size; ++i)
{
const GifColorType * const color = &cmap->Colors[gif->SavedImages[0].RasterBits[i]];
img.data[i * 3] = color->Red;
img.data[i * 3 + 1] = color->Green;
img.data[i * 3 + 2] = color->Blue;
}
DGifCloseFile(gif);
display = XOpenDisplay(NULL);
if (display == NULL)
{
return 1;
}
attr.event_mask = KeyPressMask | ExposureMask;
window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
img.width, img.height, 0, CopyFromParent,
InputOutput, CopyFromParent, CWEventMask, &attr);
XMapWindow(display, window);
while (1)
{
XEvent event;
XNextEvent(display, &event);
switch (event.type)
{
case KeyPress:
return 0;
case Expose:
XPutImage(display, window, DefaultGC(display, DefaultScreen(display)),
&img, 0, 0, 0, 0, img.width, img.height);
break;
default:
break;
}
}
}
<<attachment: interlaced.gif>>
<<attachment: expected.png>>
<<attachment: actual.png>>
diff -uNrp giflib-4.1.6.orig/lib/dgif_lib.c giflib-4.1.6/lib/dgif_lib.c
--- giflib-4.1.6.orig/lib/dgif_lib.c 2011-07-22 10:47:51.000000000 +0000
+++ giflib-4.1.6/lib/dgif_lib.c 2011-07-22 12:48:03.099742104 +0000
@@ -1056,9 +1056,35 @@ DGifSlurp(GifFileType * GifFile) {
if (sp->RasterBits == NULL) {
return GIF_ERROR;
}
- if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
- GIF_ERROR)
- return (GIF_ERROR);
+ if (sp->ImageDesc.Interlace) {
+ const int w = sp->ImageDesc.Width, h = sp->ImageDesc.Height;
+ int i;
+
+ for (i = 0; i < h; i += 8) {
+ if (DGifGetLine(GifFile, sp->RasterBits + w * i, w) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ }
+ for (i = 4; i < h; i += 8) {
+ if (DGifGetLine(GifFile, sp->RasterBits + w * i, w) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ }
+ for (i = 2; i < h; i += 4) {
+ if (DGifGetLine(GifFile, sp->RasterBits + w * i, w) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ }
+ for (i = 1; i < h; i += 2) {
+ if (DGifGetLine(GifFile, sp->RasterBits + w * i, w) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ }
+ } else {
+ if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ }
if (temp_save.ExtensionBlocks) {
sp->ExtensionBlocks = temp_save.ExtensionBlocks;
sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;

