summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2018-12-04 16:51:36 +1300
committerRobert Ancell <robert.ancell@canonical.com>2019-01-16 15:47:09 +1300
commitb9b12bfd5c6f8394cc9a4a548bd6dc0f5fb2f70b (patch)
treedfd082ef8439c313cf44dacaa5d740f150534b61
parent06afde5c45b58dd20a366d3dcb85d7e6fd702096 (diff)
downloadgdk-pixbuf-b9b12bfd5c6f8394cc9a4a548bd6dc0f5fb2f70b.tar.gz
gif: Fix multiple LZW clear codes breaking decoding
The following was occurring: 1. A clear code is detected in the LZW stream 2. The first code is detected as a clear. 3. The following code is returned as a color index, this breaks if it is a clear. There were two codepaths in use, one for handling the first clear in the LZW sequence and another for handling clears within the sequence. The former handled sequential clears correctly, the latter did not. The solution is to the correct codepath and remove the other one. This simplification should not affect other decoding (as confirmed by the test suite).
-rw-r--r--gdk-pixbuf/io-gif.c40
-rw-r--r--tests/test-images/gif-test-suite/TESTS4
2 files changed, 3 insertions, 41 deletions
diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c
index 3986635bc..244d8788f 100644
--- a/gdk-pixbuf/io-gif.c
+++ b/gdk-pixbuf/io-gif.c
@@ -86,7 +86,6 @@ enum {
GIF_GET_COLORMAP2,
GIF_PREPARE_LZW,
GIF_LZW_FILL_BUFFER,
- GIF_LZW_CLEAR_CODE,
GIF_GET_LZW,
GIF_DONE
};
@@ -162,7 +161,6 @@ struct _GifContext
int code_lastbit;
int code_done;
int code_last_byte;
- int lzw_code_pending;
/* lzw context */
gint lzw_fresh;
@@ -554,29 +552,6 @@ get_code (GifContext *context,
return ret;
}
-
-static void
-set_gif_lzw_clear_code (GifContext *context)
-{
- context->state = GIF_LZW_CLEAR_CODE;
- context->lzw_code_pending = -1;
-}
-
-static int
-gif_lzw_clear_code (GifContext *context)
-{
- gint code;
-
- code = get_code (context, context->lzw_code_size);
- if (code == -3)
- return -0;
-
- context->lzw_firstcode = context->lzw_oldcode = code;
- context->lzw_code_pending = code;
- context->state = GIF_GET_LZW;
- return 0;
-}
-
#define CHECK_LZW_SP() G_STMT_START { \
if ((guchar *)context->lzw_sp >= \
(guchar *)context->lzw_stack + sizeof (context->lzw_stack)) { \
@@ -596,12 +571,6 @@ lzw_read_byte (GifContext *context)
gint my_retval;
register int i;
- if (context->lzw_code_pending != -1) {
- retval = context->lzw_code_pending;
- context->lzw_code_pending = -1;
- return retval;
- }
-
if (context->lzw_fresh) {
context->lzw_fresh = FALSE;
do {
@@ -632,8 +601,7 @@ lzw_read_byte (GifContext *context)
context->lzw_max_code_size = 2 * context->lzw_clear_code;
context->lzw_max_code = context->lzw_clear_code + 2;
context->lzw_sp = context->lzw_stack;
-
- set_gif_lzw_clear_code (context);
+ context->lzw_fresh = TRUE;
return -3;
} else if (code == context->lzw_end_code) {
int count;
@@ -1136,7 +1104,6 @@ static void
gif_set_prepare_lzw (GifContext *context)
{
context->state = GIF_PREPARE_LZW;
- context->lzw_code_pending = -1;
}
static int
gif_prepare_lzw (GifContext *context)
@@ -1444,11 +1411,6 @@ gif_main_loop (GifContext *context)
retval = gif_lzw_fill_buffer (context);
break;
- case GIF_LZW_CLEAR_CODE:
- LOG("clear_code\n");
- retval = gif_lzw_clear_code (context);
- break;
-
case GIF_GET_LZW:
LOG("get_lzw\n");
retval = gif_get_lzw (context);
diff --git a/tests/test-images/gif-test-suite/TESTS b/tests/test-images/gif-test-suite/TESTS
index cc986661e..1d4a3f13f 100644
--- a/tests/test-images/gif-test-suite/TESTS
+++ b/tests/test-images/gif-test-suite/TESTS
@@ -33,8 +33,8 @@ extra-data
no-clear
no-eoi
no-clear-and-eoi
-#many-clears
-#double-clears
+many-clears
+double-clears
invalid-colors
max-width
max-height