diff options
author | Sean Fox <dyntryx@gmail.com> | 2009-01-03 07:01:10 +0000 |
---|---|---|
committer | Sean Fox <dyntryx@gmail.com> | 2009-01-03 07:01:10 +0000 |
commit | 2247ced70842f51bdd90577b6a9e20b465674e46 (patch) | |
tree | ff139b44a9d1f55504c7c805c26cb0fae14d5adb | |
parent | a49d9b5869e27596e5fcc2957ec3ce7de7800045 (diff) | |
download | libnsgif-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.c | 33 | ||||
-rw-r--r-- | libnsgif.h | 3 |
2 files changed, 30 insertions, 6 deletions
@@ -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]; @@ -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 |