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)