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;