summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Fox <dyntryx@gmail.com>2009-01-03 07:01:10 +0000
committerSean Fox <dyntryx@gmail.com>2009-01-03 07:01:10 +0000
commit2247ced70842f51bdd90577b6a9e20b465674e46 (patch)
treeff139b44a9d1f55504c7c805c26cb0fae14d5adb
parenta49d9b5869e27596e5fcc2957ec3ce7de7800045 (diff)
downloadlibnsgif-2247ced70842f51bdd90577b6a9e20b465674e46.tar.gz
libnsgif-2247ced70842f51bdd90577b6a9e20b465674e46.tar.bz2
When a frame claims to exceed the GIF's buffer, libnsgif will now try to recover by rendering the available frame data instead of returning an error and dropping the frame completely. This same concept may be applicable in other libnsgif locations.
svn path=/trunk/libnsgif/; revision=5957
-rw-r--r--libnsgif.c33
-rw-r--r--libnsgif.h3
2 files changed, 30 insertions, 6 deletions
diff --git a/libnsgif.c b/libnsgif.c
index 0146414..8079347 100644
--- a/libnsgif.c
+++ b/libnsgif.c
@@ -574,9 +574,27 @@ static gif_result gif_initialise_frame(gif_animation *gif) {
block_size = 0;
while (block_size != 1) {
block_size = gif_data[0] + 1;
- if ((gif_bytes -= block_size) < 0)
- return GIF_INSUFFICIENT_FRAME_DATA;
- gif_data += block_size;
+ /* Check if the frame data runs off the end of the file
+ */
+ if ((int)(gif_bytes - block_size) < 0) {
+ /* Try to recover by signaling the end of the gif.
+ * Once we get garbage data, there is no logical
+ * way to determine where the next frame is.
+ * It's probably better to partially load the gif
+ * than not at all.
+ */
+ if (gif_bytes >= 2) {
+ gif_data[0] = 0;
+ gif_data[1] = GIF_TRAILER;
+ gif_bytes = 1;
+ ++gif_data;
+ break;
+ } else
+ return GIF_INSUFFICIENT_FRAME_DATA;
+ } else {
+ gif_bytes -= block_size;
+ gif_data += block_size;
+ }
}
/* Add the frame and set the display flag
@@ -957,7 +975,12 @@ gif_result gif_decode_frame(gif_animation *gif, unsigned int frame) {
}
} else {
if (!gif_next_LZW(gif)) {
- return_value = gif->current_error;
+ /* Unexpected end of frame, try to recover
+ */
+ if (gif->current_error == GIF_END_OF_FRAME)
+ return_value = GIF_OK;
+ else
+ return_value = gif->current_error;
goto gif_decode_frame_exit;
}
}
@@ -1190,7 +1213,7 @@ static int gif_next_code(gif_animation *gif, int code_size) {
end = curbit + code_size;
if (end >= lastbit) {
if (get_done)
- return GIF_INSUFFICIENT_FRAME_DATA;
+ return GIF_END_OF_FRAME;
buf[0] = direct[last_byte - 2];
buf[1] = direct[last_byte - 1];
diff --git a/libnsgif.h b/libnsgif.h
index 76207c9..1710601 100644
--- a/libnsgif.h
+++ b/libnsgif.h
@@ -36,7 +36,8 @@ typedef enum {
GIF_INSUFFICIENT_DATA = -3,
GIF_DATA_ERROR = -4,
GIF_INSUFFICIENT_MEMORY = -5,
- GIF_FRAME_NO_DISPLAY = -6
+ GIF_FRAME_NO_DISPLAY = -6,
+ GIF_END_OF_FRAME = -7
} gif_result;
/* The GIF frame data