Add wuffs_gif__quirk_reject_empty_frame
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 28854b1..1cb3e28 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -3286,6 +3286,7 @@
extern const char* wuffs_gif__error__bad_block;
extern const char* wuffs_gif__error__bad_extension_label;
+extern const char* wuffs_gif__error__bad_frame_size;
extern const char* wuffs_gif__error__bad_graphic_control;
extern const char* wuffs_gif__error__bad_header;
extern const char* wuffs_gif__error__bad_literal_width;
@@ -3323,6 +3324,12 @@
wuffs_gif__quirk_background_is_opaque //
WUFFS_BASE__POTENTIALLY_UNUSED = 1041635331;
+#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333
+
+static const uint32_t //
+ wuffs_gif__quirk_reject_empty_frame //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635333;
+
#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635332
static const uint32_t //
@@ -3445,6 +3452,7 @@
bool f_quirk_enabled_ignore_too_much_pixel_data;
bool f_quirk_enabled_image_bounds_are_strict;
bool f_quirk_enabled_background_is_opaque;
+ bool f_quirk_enabled_reject_empty_frame;
bool f_quirk_enabled_reject_empty_palette;
bool f_delayed_num_decoded_frames;
bool f_end_of_data;
@@ -8560,6 +8568,7 @@
const char* wuffs_gif__error__bad_block = "#gif: bad block";
const char* wuffs_gif__error__bad_extension_label = "#gif: bad extension label";
+const char* wuffs_gif__error__bad_frame_size = "#gif: bad frame size";
const char* wuffs_gif__error__bad_graphic_control = "#gif: bad graphic control";
const char* wuffs_gif__error__bad_header = "#gif: bad header";
const char* wuffs_gif__error__bad_literal_width = "#gif: bad literal width";
@@ -8747,6 +8756,8 @@
self->private_impl.f_quirk_enabled_image_bounds_are_strict = a_enabled;
} else if (a_quirk == 1041635331) {
self->private_impl.f_quirk_enabled_background_is_opaque = a_enabled;
+ } else if (a_quirk == 1041635333) {
+ self->private_impl.f_quirk_enabled_reject_empty_frame = a_enabled;
} else if (a_quirk == 1041635332) {
self->private_impl.f_quirk_enabled_reject_empty_palette = a_enabled;
}
@@ -10592,6 +10603,14 @@
self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0;
self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0;
+ if (self->private_impl.f_quirk_enabled_reject_empty_frame &&
+ ((self->private_impl.f_frame_rect_x0 ==
+ self->private_impl.f_frame_rect_x1) ||
+ (self->private_impl.f_frame_rect_y0 ==
+ self->private_impl.f_frame_rect_y1))) {
+ status = wuffs_gif__error__bad_frame_size;
+ goto exit;
+ }
if ((self->private_impl.f_call_sequence == 0) &&
!self->private_impl.f_quirk_enabled_image_bounds_are_strict) {
self->private_impl.f_width = wuffs_base__u32__max(
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 9251162..76c94fa 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -16,6 +16,7 @@
pub status "#bad block"
pub status "#bad extension label"
+pub status "#bad frame size"
pub status "#bad graphic control"
pub status "#bad header"
pub status "#bad literal width"
@@ -100,6 +101,9 @@
// buffer with that color.
pub const quirk_background_is_opaque base.u32 = (0xF8586 << 10) | 3
+// When this quirk is enabled, a frame with zero width or height is rejected.
+pub const quirk_reject_empty_frame base.u32 = (0xF8586 << 10) | 5
+
// 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
@@ -174,6 +178,7 @@
quirk_enabled_ignore_too_much_pixel_data base.bool,
quirk_enabled_image_bounds_are_strict base.bool,
quirk_enabled_background_is_opaque base.bool,
+ quirk_enabled_reject_empty_frame base.bool,
quirk_enabled_reject_empty_palette base.bool,
delayed_num_decoded_frames base.bool,
@@ -239,6 +244,8 @@
this.quirk_enabled_image_bounds_are_strict = args.enabled
} else if args.quirk == quirk_background_is_opaque {
this.quirk_enabled_background_is_opaque = args.enabled
+ } else if args.quirk == quirk_reject_empty_frame {
+ this.quirk_enabled_reject_empty_frame = args.enabled
} else if args.quirk == quirk_reject_empty_palette {
this.quirk_enabled_reject_empty_palette = args.enabled
}
@@ -825,6 +832,12 @@
this.dst_x = this.frame_rect_x0
this.dst_y = this.frame_rect_y0
+ if this.quirk_enabled_reject_empty_frame and
+ ((this.frame_rect_x0 == this.frame_rect_x1) or
+ (this.frame_rect_y0 == this.frame_rect_y1)) {
+ return "#bad frame size"
+ }
+
// Set the image's overall width and height to be the maximum of the
// nominal image width and height (given in the Logical Screen Descriptor)
// and the bottom right extent of the first frame. See
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 7457045..ee1d94b 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -1096,7 +1096,7 @@
return status;
}
int q;
- for (q = 0; q < 2; q++) {
+ for (q = 0; q < 3; q++) {
src.meta.ri = 0;
wuffs_gif__decoder dec;
@@ -1106,13 +1106,35 @@
if (status) {
RETURN_FAIL("q=%d: initialize: \"%s\"", q, status);
}
- wuffs_gif__decoder__set_quirk_enabled(
- &dec, wuffs_gif__quirk_ignore_too_much_pixel_data, q);
+
+ const char* want = NULL;
+ switch (q) {
+ case 0:
+ want = wuffs_base__error__too_much_data;
+ break;
+ case 1:
+ want = NULL;
+ wuffs_gif__decoder__set_quirk_enabled(
+ &dec, wuffs_gif__quirk_ignore_too_much_pixel_data, true);
+ break;
+ case 2:
+ want = wuffs_gif__error__bad_frame_size;
+ wuffs_gif__decoder__set_quirk_enabled(
+ &dec, wuffs_gif__quirk_reject_empty_frame, true);
+ break;
+ }
wuffs_base__image_config ic = ((wuffs_base__image_config){});
status = wuffs_gif__decoder__decode_image_config(
&dec, &ic, wuffs_base__io_buffer__reader(&src));
if (status) {
+ if (q == 2) {
+ if (status != want) {
+ RETURN_FAIL("q=%d: decode_image_config: got \"%s\", want \"%s\"", q,
+ status, want);
+ }
+ continue;
+ }
RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
}
@@ -1123,12 +1145,12 @@
RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status);
}
- const char* got = wuffs_gif__decoder__decode_frame(
+ status = wuffs_gif__decoder__decode_frame(
&dec, &pb, wuffs_base__io_buffer__reader(&src), global_work_slice,
NULL);
- const char* want = q ? NULL : wuffs_base__error__too_much_data;
- if (got != want) {
- RETURN_FAIL("q=%d: decode_frame: got \"%s\", want \"%s\"", q, got, want);
+ if (status != want) {
+ RETURN_FAIL("q=%d: decode_frame: got \"%s\", want \"%s\"", q, status,
+ want);
}
}
return NULL;