Reject bad LZW widths when skipping GIF frames
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 5b40d60..b4f77fc 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -9228,6 +9228,7 @@
wuffs_base__status status = NULL;
uint8_t v_flags = 0;
+ uint8_t v_lw = 0;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
@@ -9273,12 +9274,19 @@
}
iop_a_src += self->private_data.s_skip_frame[0].scratch;
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
- status = wuffs_base__suspension__short_read;
- goto suspend;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ uint8_t t_1 = *iop_a_src++;
+ v_lw = t_1;
}
- iop_a_src++;
+ if ((v_lw < 1) || (8 < v_lw)) {
+ status = wuffs_gif__error__bad_literal_width;
+ goto exit;
+ }
if (a_src.private_impl.buf) {
a_src.private_impl.buf->meta.ri =
((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 3298f3b..2f1fce8 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -392,14 +392,20 @@
pri func decoder.skip_frame?(src base.io_reader) {
var flags base.u8
+ var lw base.u8
// Skip the optional Local Color Table, 3 bytes (RGB) per entry.
flags = args.src.read_u8?()
if (flags & 0x80) <> 0 {
args.src.skip?(n:(3 as base.u32) << (1 + (flags & 0x07)))
}
- // Skip the literal width.
- args.src.skip?(n:1)
+
+ // Process the LZW literal width.
+ lw = args.src.read_u8?()
+ if (lw < 1) or (8 < lw) {
+ return "#bad literal width"
+ }
+
// Skip the blocks of LZW-compressed data.
this.skip_blocks?(src:args.src)