Prepare to add gif quirks
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index f04c0e3..7034209 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -3277,6 +3277,30 @@
     wuffs_gif__decoder_workbuf_len_max_incl_worst_case  //
         WUFFS_BASE__POTENTIALLY_UNUSED = 1;
 
+#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635329
+
+static const uint32_t                            //
+    wuffs_gif__quirk_ignore_too_much_pixel_data  //
+        WUFFS_BASE__POTENTIALLY_UNUSED = 1041635329;
+
+#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635330
+
+static const uint32_t                         //
+    wuffs_gif__quirk_image_bounds_are_strict  //
+        WUFFS_BASE__POTENTIALLY_UNUSED = 1041635330;
+
+#define WUFFS_GIF__QUIRK_INITIAL_BACKGROUND_IS_OPAQUE 1041635331
+
+static const uint32_t                              //
+    wuffs_gif__quirk_initial_background_is_opaque  //
+        WUFFS_BASE__POTENTIALLY_UNUSED = 1041635331;
+
+#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635332
+
+static const uint32_t                      //
+    wuffs_gif__quirk_reject_empty_palette  //
+        WUFFS_BASE__POTENTIALLY_UNUSED = 1041635332;
+
 // ---------------- Struct Declarations
 
 typedef struct wuffs_gif__decoder__struct wuffs_gif__decoder;
@@ -3300,6 +3324,11 @@
 
 // ---------------- Public Function Prototypes
 
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct  //
+wuffs_gif__decoder__set_quirk_enabled(wuffs_gif__decoder* self,
+                                      uint32_t a_quirk,
+                                      bool a_enabled);
+
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_gif__decoder__decode_image_config(wuffs_gif__decoder* self,
                                         wuffs_base__image_config* a_dst,
@@ -3384,6 +3413,10 @@
     uint32_t f_metadata_fourcc_value;
     uint64_t f_metadata_chunk_length_value;
     uint64_t f_metadata_io_position;
+    bool f_quirk_enabled_ignore_too_much_pixel_data;
+    bool f_quirk_enabled_image_bounds_are_strict;
+    bool f_quirk_enabled_initial_background_is_opaque;
+    bool f_quirk_enabled_reject_empty_palette;
     bool f_end_of_data;
     bool f_restarted;
     bool f_previous_lzw_decode_ended_abruptly;
@@ -3508,6 +3541,11 @@
                                           initialize_flags);
   }
 
+  inline wuffs_base__empty_struct  //
+  set_quirk_enabled(uint32_t a_quirk, bool a_enabled) {
+    return wuffs_gif__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
+  }
+
   inline wuffs_base__status  //
   decode_image_config(wuffs_base__image_config* a_dst,
                       wuffs_base__io_reader a_src) {
@@ -8655,6 +8693,31 @@
 
 // ---------------- Function Implementations
 
+// -------- func gif.decoder.set_quirk_enabled
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct  //
+wuffs_gif__decoder__set_quirk_enabled(wuffs_gif__decoder* self,
+                                      uint32_t a_quirk,
+                                      bool a_enabled) {
+  if (!self) {
+    return wuffs_base__make_empty_struct();
+  }
+  if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+    return wuffs_base__make_empty_struct();
+  }
+
+  if (a_quirk == 1041635329) {
+    self->private_impl.f_quirk_enabled_ignore_too_much_pixel_data = a_enabled;
+  } else if (a_quirk == 1041635330) {
+    self->private_impl.f_quirk_enabled_image_bounds_are_strict = a_enabled;
+  } else if (a_quirk == 1041635331) {
+    self->private_impl.f_quirk_enabled_initial_background_is_opaque = a_enabled;
+  } else if (a_quirk == 1041635332) {
+    self->private_impl.f_quirk_enabled_reject_empty_palette = a_enabled;
+  }
+  return wuffs_base__make_empty_struct();
+}
+
 // -------- func gif.decoder.decode_image_config
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index fa09513..3a15ebb 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -27,6 +27,41 @@
 // need a per-pixel-row workbuf.
 pub const decoder_workbuf_len_max_incl_worst_case base.u64 = 1
 
+// --------
+
+// Quirks.
+//
+// A base38 (github.com/google/wuffs/lib/base38) value can fit in 21 bits.
+// Leaving the high bit of a uint32 reserved, the low 10 bits can be used for
+// package-specific quirk constants: the base38 value acts as a namespace.
+
+// The base38 encoding of "gif " is 0xF8586.
+
+// When this quirk is enabled, silently ignore e.g. a frame that reports a
+// width and height of 6 pixels each, followed by 50 pixel values. In that
+// case, we process the first 36 pixel values and discard the excess 14.
+pub const quirk_ignore_too_much_pixel_data base.u32 = (0xF8586 << 10) | 1
+
+// When this quirk is enabled, if the initial frame bounds extends beyond the
+// image bounds, then the image bounds stay unchanged. By default (with this
+// quirk disabled), the image bounds are adjusted to always contain the first
+// frame's bounds (but not necessarily subsequent frame's bounds).
+//
+// For more discussion, see
+// https://github.com/google/wuffs/blob/master/test/data/artificial/gif-frame-out-of-bounds.gif.make-artificial.txt
+pub const quirk_image_bounds_are_strict base.u32 = (0xF8586 << 10) | 2
+
+// When this quirk is enabled, if the initial frame bounds is smaller than the
+// image bounds, those pixels outside the initial frame bounds are assumed to
+// start as opaque black instead of transparent black.
+pub const quirk_initial_background_is_opaque base.u32 = (0xF8586 << 10) | 3
+
+// When this quirk is enabled, a frame with no explicit palette is rejected,
+// instead of implicitly having a palette with every entry being opaque black.
+pub const quirk_reject_empty_palette base.u32 = (0xF8586 << 10) | 4
+
+// --------
+
 // See the spec appendix E "Interlaced Images" on page 29. The first element
 // represents either that the frame was non-interlaced, or that all interlace
 // stages are complete. Otherwise, the four interlace stages are elements 4, 3,
@@ -91,6 +126,11 @@
 	metadata_chunk_length_value base.u64,
 	metadata_io_position        base.u64,
 
+	quirk_enabled_ignore_too_much_pixel_data   base.bool,
+	quirk_enabled_image_bounds_are_strict      base.bool,
+	quirk_enabled_initial_background_is_opaque base.bool,
+	quirk_enabled_reject_empty_palette         base.bool,
+
 	end_of_data                        base.bool,
 	restarted                          base.bool,
 	previous_lzw_decode_ended_abruptly base.bool,
@@ -143,6 +183,18 @@
 	lzw lzw.decoder,
 )
 
+pub func decoder.set_quirk_enabled!(quirk base.u32, enabled base.bool) {
+	if args.quirk == quirk_ignore_too_much_pixel_data {
+		this.quirk_enabled_ignore_too_much_pixel_data = args.enabled
+	} else if args.quirk == quirk_image_bounds_are_strict {
+		this.quirk_enabled_image_bounds_are_strict = args.enabled
+	} else if args.quirk == quirk_initial_background_is_opaque {
+		this.quirk_enabled_initial_background_is_opaque = args.enabled
+	} else if args.quirk == quirk_reject_empty_palette {
+		this.quirk_enabled_reject_empty_palette = args.enabled
+	}
+}
+
 pub func decoder.decode_image_config?(dst nptr base.image_config, src base.io_reader) {
 	var ffio base.bool