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;

Reply via email to