Gitweb links:
...log
http://git.netsurf-browser.org/libnsgif.git/shortlog/088fa0819f1aeaf212a9...
...commit
http://git.netsurf-browser.org/libnsgif.git/commit/088fa0819f1aeaf212a95c...
...tree
http://git.netsurf-browser.org/libnsgif.git/tree/088fa0819f1aeaf212a95caf...
The branch, master has been updated
via 088fa0819f1aeaf212a95caf7393a38c1640b5f0 (commit)
via a268d2c15252ac58c19f1b19771822c66bcf73b2 (commit)
via 5446c3c056f30d98c725e1899a92e104ad70c7e0 (commit)
from 0c97f24173d461cd07e06da5f419bd1238cbd6e6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=088fa0819f1aeaf212...
commit 088fa0819f1aeaf212a95caf7393a38c1640b5f0
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Ensure code is valid before use.
Issue-reported-by: Hans Jerry Illikainen
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 4e45c50..87371f2 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -1221,7 +1221,8 @@ static bool gif_next_LZW(gif_animation *gif) {
*
* Note: our stack is always big enough to hold a complete decompressed chunk. */
while (code >= clear_code) {
- if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2) ||
+ code >= (1 << GIF_MAX_LZW)) {
gif->current_error = GIF_FRAME_DATA_ERROR;
return false;
}
@@ -1232,7 +1233,8 @@ static bool gif_next_LZW(gif_animation *gif) {
break;
}
- if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2) ||
+ new_code >= (1 << GIF_MAX_LZW)) {
gif->current_error = GIF_FRAME_DATA_ERROR;
return false;
}
diff --git a/test/data/lzwoob.gif b/test/data/lzwoob.gif
new file mode 100644
index 0000000..c0c03b5
Binary files /dev/null and b/test/data/lzwoob.gif differ
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=a268d2c15252ac58c1...
commit a268d2c15252ac58c19f1b19771822c66bcf73b2
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Ensure LZW decode stack does not overflow.
Issue-reported-by: Hans Jerry Illikainen
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 0047ee0..4e45c50 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -1208,6 +1208,10 @@ static bool gif_next_LZW(gif_animation *gif) {
incode = code;
if (code >= max_code) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = firstcode;
code = oldcode;
}
@@ -1217,12 +1221,21 @@ static bool gif_next_LZW(gif_animation *gif) {
*
* Note: our stack is always big enough to hold a complete decompressed chunk. */
while (code >= clear_code) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = table[1][code];
new_code = table[0][code];
if (new_code < clear_code) {
code = new_code;
break;
}
+
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = table[1][new_code];
code = table[0][new_code];
if (code == new_code) {
@@ -1231,6 +1244,10 @@ static bool gif_next_LZW(gif_animation *gif) {
}
}
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = firstcode = table[1][code];
if ((code = max_code) < (1 << GIF_MAX_LZW)) {
diff --git a/test/data/lzwof.gif b/test/data/lzwof.gif
new file mode 100644
index 0000000..43081ea
Binary files /dev/null and b/test/data/lzwof.gif differ
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=5446c3c056f30d98c7...
commit 5446c3c056f30d98c725e1899a92e104ad70c7e0
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Improve checks for data buffer exhaustion
diff --git a/src/libnsgif.c b/src/libnsgif.c
index dd44a43..0047ee0 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -513,6 +513,7 @@ static gif_result gif_initialise_frame(gif_animation *gif) {
/* Do some simple boundary checking
*/
+ if (gif_bytes < 10) return GIF_INSUFFICIENT_FRAME_DATA;
offset_x = gif_data[1] | (gif_data[2] << 8);
offset_y = gif_data[3] | (gif_data[4] << 8);
width = gif_data[5] | (gif_data[6] << 8);
@@ -574,20 +575,22 @@ static gif_result gif_initialise_frame(gif_animation *gif) {
/* Ensure we have a correct code size
*/
+ if (gif_bytes < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
if (gif_data[0] > GIF_MAX_LZW)
return GIF_DATA_ERROR;
/* Move our pointer to the actual image data
*/
gif_data++;
- if (--gif_bytes < 0)
- return GIF_INSUFFICIENT_FRAME_DATA;
+ --gif_bytes;
/* Repeatedly skip blocks until we get a zero block or run out of data
* These blocks of image data are processed later by gif_decode_frame()
*/
block_size = 0;
while (block_size != 1) {
+ if (gif_bytes < 1) return GIF_INSUFFICIENT_FRAME_DATA;
block_size = gif_data[0] + 1;
/* Check if the frame data runs off the end of the file
*/
@@ -644,9 +647,10 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
/* Initialise the extensions
*/
- while (gif_data[0] == GIF_EXTENSION_INTRODUCER) {
+ while (gif_data < gif_end && gif_data[0] == GIF_EXTENSION_INTRODUCER) {
++gif_data;
- gif_bytes = (gif_end - gif_data);
+ if ((gif_bytes = (gif_end - gif_data)) < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
/* Switch on extension label
*/
@@ -713,6 +717,7 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
* Skip the extension size itself
*/
default:
+ if (gif_bytes < 2) return GIF_INSUFFICIENT_FRAME_DATA;
gif_data += (2 + gif_data[1]);
}
@@ -721,7 +726,7 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
*/
gif_bytes = (gif_end - gif_data);
block_size = 0;
- while (gif_data[0] != GIF_BLOCK_TERMINATOR) {
+ while (gif_data < gif_end && gif_data[0] != GIF_BLOCK_TERMINATOR) {
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
@@ -1070,8 +1075,10 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
/* Skip the extensions
*/
- while (gif_data[0] == GIF_EXTENSION_INTRODUCER) {
+ while (gif_data < gif_end && gif_data[0] == GIF_EXTENSION_INTRODUCER) {
++gif_data;
+ if (gif_data >= gif_end)
+ return GIF_INSUFFICIENT_FRAME_DATA;
/* Switch on extension label
*/
@@ -1088,6 +1095,8 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
* Skip the extension size itself
*/
default:
+ if (gif_data + 1 >= gif_end)
+ return GIF_INSUFFICIENT_FRAME_DATA;
gif_data += (2 + gif_data[1]);
}
@@ -1096,7 +1105,7 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
*/
gif_bytes = (gif_end - gif_data);
block_size = 0;
- while (gif_data[0] != GIF_BLOCK_TERMINATOR) {
+ while (gif_data < gif_end && gif_data[0] != GIF_BLOCK_TERMINATOR) {
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
@@ -1188,7 +1197,8 @@ static bool gif_next_LZW(gif_animation *gif) {
return false;
}
block_size = 0;
- while (block_size != 1) {
+ while (block_size != 1 &&
+ gif->buffer_position < gif->buffer_size) {
block_size = gif->gif_data[gif->buffer_position] + 1;
gif->buffer_position += block_size;
}
@@ -1249,12 +1259,16 @@ static int gif_next_code(gif_animation *gif, int code_size) {
/* get the next block */
direct = gif->gif_data + gif->buffer_position;
+ if (gif->buffer_position >= gif->buffer_size)
+ return GIF_INSUFFICIENT_FRAME_DATA;
zero_data_block = ((count = direct[0]) == 0);
if ((gif->buffer_position + count) >= gif->buffer_size)
return GIF_INSUFFICIENT_FRAME_DATA;
if (count == 0)
get_done = true;
else {
+ if (gif->buffer_position + 3 >= gif->buffer_size)
+ return GIF_INSUFFICIENT_FRAME_DATA;
direct -= 1;
buf[2] = direct[2];
buf[3] = direct[3];
-----------------------------------------------------------------------
Summary of changes:
src/libnsgif.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
test/data/lzwof.gif | Bin 0 -> 40 bytes
test/data/lzwoob.gif | Bin 0 -> 40 bytes
3 files changed, 41 insertions(+), 8 deletions(-)
create mode 100644 test/data/lzwof.gif
create mode 100644 test/data/lzwoob.gif
diff --git a/src/libnsgif.c b/src/libnsgif.c
index dd44a43..87371f2 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -513,6 +513,7 @@ static gif_result gif_initialise_frame(gif_animation *gif) {
/* Do some simple boundary checking
*/
+ if (gif_bytes < 10) return GIF_INSUFFICIENT_FRAME_DATA;
offset_x = gif_data[1] | (gif_data[2] << 8);
offset_y = gif_data[3] | (gif_data[4] << 8);
width = gif_data[5] | (gif_data[6] << 8);
@@ -574,20 +575,22 @@ static gif_result gif_initialise_frame(gif_animation *gif) {
/* Ensure we have a correct code size
*/
+ if (gif_bytes < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
if (gif_data[0] > GIF_MAX_LZW)
return GIF_DATA_ERROR;
/* Move our pointer to the actual image data
*/
gif_data++;
- if (--gif_bytes < 0)
- return GIF_INSUFFICIENT_FRAME_DATA;
+ --gif_bytes;
/* Repeatedly skip blocks until we get a zero block or run out of data
* These blocks of image data are processed later by gif_decode_frame()
*/
block_size = 0;
while (block_size != 1) {
+ if (gif_bytes < 1) return GIF_INSUFFICIENT_FRAME_DATA;
block_size = gif_data[0] + 1;
/* Check if the frame data runs off the end of the file
*/
@@ -644,9 +647,10 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
/* Initialise the extensions
*/
- while (gif_data[0] == GIF_EXTENSION_INTRODUCER) {
+ while (gif_data < gif_end && gif_data[0] == GIF_EXTENSION_INTRODUCER) {
++gif_data;
- gif_bytes = (gif_end - gif_data);
+ if ((gif_bytes = (gif_end - gif_data)) < 1)
+ return GIF_INSUFFICIENT_FRAME_DATA;
/* Switch on extension label
*/
@@ -713,6 +717,7 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
* Skip the extension size itself
*/
default:
+ if (gif_bytes < 2) return GIF_INSUFFICIENT_FRAME_DATA;
gif_data += (2 + gif_data[1]);
}
@@ -721,7 +726,7 @@ static gif_result gif_initialise_frame_extensions(gif_animation *gif,
const int
*/
gif_bytes = (gif_end - gif_data);
block_size = 0;
- while (gif_data[0] != GIF_BLOCK_TERMINATOR) {
+ while (gif_data < gif_end && gif_data[0] != GIF_BLOCK_TERMINATOR) {
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
@@ -1070,8 +1075,10 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
/* Skip the extensions
*/
- while (gif_data[0] == GIF_EXTENSION_INTRODUCER) {
+ while (gif_data < gif_end && gif_data[0] == GIF_EXTENSION_INTRODUCER) {
++gif_data;
+ if (gif_data >= gif_end)
+ return GIF_INSUFFICIENT_FRAME_DATA;
/* Switch on extension label
*/
@@ -1088,6 +1095,8 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
* Skip the extension size itself
*/
default:
+ if (gif_data + 1 >= gif_end)
+ return GIF_INSUFFICIENT_FRAME_DATA;
gif_data += (2 + gif_data[1]);
}
@@ -1096,7 +1105,7 @@ static gif_result gif_skip_frame_extensions(gif_animation *gif) {
*/
gif_bytes = (gif_end - gif_data);
block_size = 0;
- while (gif_data[0] != GIF_BLOCK_TERMINATOR) {
+ while (gif_data < gif_end && gif_data[0] != GIF_BLOCK_TERMINATOR) {
block_size = gif_data[0] + 1;
if ((gif_bytes -= block_size) < 0)
return GIF_INSUFFICIENT_FRAME_DATA;
@@ -1188,7 +1197,8 @@ static bool gif_next_LZW(gif_animation *gif) {
return false;
}
block_size = 0;
- while (block_size != 1) {
+ while (block_size != 1 &&
+ gif->buffer_position < gif->buffer_size) {
block_size = gif->gif_data[gif->buffer_position] + 1;
gif->buffer_position += block_size;
}
@@ -1198,6 +1208,10 @@ static bool gif_next_LZW(gif_animation *gif) {
incode = code;
if (code >= max_code) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = firstcode;
code = oldcode;
}
@@ -1207,12 +1221,23 @@ static bool gif_next_LZW(gif_animation *gif) {
*
* Note: our stack is always big enough to hold a complete decompressed chunk. */
while (code >= clear_code) {
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2) ||
+ code >= (1 << GIF_MAX_LZW)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = table[1][code];
new_code = table[0][code];
if (new_code < clear_code) {
code = new_code;
break;
}
+
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2) ||
+ new_code >= (1 << GIF_MAX_LZW)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = table[1][new_code];
code = table[0][new_code];
if (code == new_code) {
@@ -1221,6 +1246,10 @@ static bool gif_next_LZW(gif_animation *gif) {
}
}
+ if (stack_pointer >= stack + ((1 << GIF_MAX_LZW) * 2)) {
+ gif->current_error = GIF_FRAME_DATA_ERROR;
+ return false;
+ }
*stack_pointer++ = firstcode = table[1][code];
if ((code = max_code) < (1 << GIF_MAX_LZW)) {
@@ -1249,12 +1278,16 @@ static int gif_next_code(gif_animation *gif, int code_size) {
/* get the next block */
direct = gif->gif_data + gif->buffer_position;
+ if (gif->buffer_position >= gif->buffer_size)
+ return GIF_INSUFFICIENT_FRAME_DATA;
zero_data_block = ((count = direct[0]) == 0);
if ((gif->buffer_position + count) >= gif->buffer_size)
return GIF_INSUFFICIENT_FRAME_DATA;
if (count == 0)
get_done = true;
else {
+ if (gif->buffer_position + 3 >= gif->buffer_size)
+ return GIF_INSUFFICIENT_FRAME_DATA;
direct -= 1;
buf[2] = direct[2];
buf[3] = direct[3];
diff --git a/test/data/lzwof.gif b/test/data/lzwof.gif
new file mode 100644
index 0000000..43081ea
Binary files /dev/null and b/test/data/lzwof.gif differ
diff --git a/test/data/lzwoob.gif b/test/data/lzwoob.gif
new file mode 100644
index 0000000..c0c03b5
Binary files /dev/null and b/test/data/lzwoob.gif differ
--
NetSurf GIF Decoder