Factor out fuzz/c/fuzzlib/fuzzlib_image_decoder.c
diff --git a/fuzz/c/fuzzlib/fuzzlib_image_decoder.c b/fuzz/c/fuzzlib/fuzzlib_image_decoder.c
new file mode 100644
index 0000000..ae3d979
--- /dev/null
+++ b/fuzz/c/fuzzlib/fuzzlib_image_decoder.c
@@ -0,0 +1,129 @@
+// Copyright 2020 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef WUFFS_INCLUDE_GUARD
+#error "Wuffs' .h files need to be included before this file"
+#endif
+
+static const char* //
+fuzz_image_decoder(wuffs_base__io_buffer* src,
+ uint64_t hash,
+ wuffs_base__image_decoder* dec) {
+ const char* ret = NULL;
+ wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
+ wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
+
+ // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
+ // variable initialization" warnings.
+ {
+ wuffs_base__image_config ic = ((wuffs_base__image_config){});
+ wuffs_base__status status =
+ wuffs_base__image_decoder__decode_image_config(dec, &ic, src);
+ if (!wuffs_base__status__is_ok(&status)) {
+ ret = wuffs_base__status__message(&status);
+ goto exit;
+ }
+ if (!wuffs_base__image_config__is_valid(&ic)) {
+ ret = "invalid image_config";
+ goto exit;
+ }
+
+ // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
+ if (hash & 1) {
+ wuffs_base__pixel_config__set(
+ &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
+ WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
+ wuffs_base__pixel_config__width(&ic.pixcfg),
+ wuffs_base__pixel_config__height(&ic.pixcfg));
+ }
+ hash >>= 1;
+
+ // Wuffs allows either statically or dynamically allocated work buffers.
+ // This program exercises dynamic allocation.
+ uint64_t n = wuffs_base__image_decoder__workbuf_len(dec).max_incl;
+ if (n > 64 * 1024 * 1024) { // Don't allocate more than 64 MiB.
+ ret = "image too large";
+ goto exit;
+ }
+ if (n > 0) {
+ workbuf = wuffs_base__malloc_slice_u8(malloc, n);
+ if (!workbuf.ptr) {
+ ret = "out of memory";
+ goto exit;
+ }
+ }
+
+ n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
+ if (n > 64 * 1024 * 1024) { // Don't allocate more than 64 MiB.
+ ret = "image too large";
+ goto exit;
+ }
+ if (n > 0) {
+ pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
+ if (!pixbuf.ptr) {
+ ret = "out of memory";
+ goto exit;
+ }
+ }
+
+ wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
+ status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
+ if (!wuffs_base__status__is_ok(&status)) {
+ ret = wuffs_base__status__message(&status);
+ goto exit;
+ }
+
+ bool seen_ok = false;
+ while (true) {
+ wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
+ status = wuffs_base__image_decoder__decode_frame_config(dec, &fc, src);
+ if (!wuffs_base__status__is_ok(&status)) {
+ if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
+ ret = wuffs_base__status__message(&status);
+ }
+ goto exit;
+ }
+
+ status = wuffs_base__image_decoder__decode_frame(
+ dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
+
+ wuffs_base__rect_ie_u32 frame_rect =
+ wuffs_base__frame_config__bounds(&fc);
+ wuffs_base__rect_ie_u32 dirty_rect =
+ wuffs_base__image_decoder__frame_dirty_rect(dec);
+ if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
+ ret = "internal error: frame_rect does not contain dirty_rect";
+ goto exit;
+ }
+
+ if (!wuffs_base__status__is_ok(&status)) {
+ if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
+ ret = wuffs_base__status__message(&status);
+ }
+ goto exit;
+ }
+ seen_ok = true;
+
+ if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
+ ret = "internal error: frame_rect does not equal dirty_rect";
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ free(workbuf.ptr);
+ free(pixbuf.ptr);
+ return ret;
+}
diff --git a/fuzz/c/std/gif_fuzzer.c b/fuzz/c/std/gif_fuzzer.c
index e8950a4..0f5de60 100644
--- a/fuzz/c/std/gif_fuzzer.c
+++ b/fuzz/c/std/gif_fuzzer.c
@@ -59,123 +59,19 @@
// program to generate a stand-alone C file.
#include "../../../release/c/wuffs-unsupported-snapshot.c"
#include "../fuzzlib/fuzzlib.c"
+#include "../fuzzlib/fuzzlib_image_decoder.c"
const char* //
fuzz(wuffs_base__io_buffer* src, uint64_t hash) {
- const char* ret = NULL;
- wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
- wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
-
- // Use a {} code block so that "goto exit" doesn't trigger "jump bypasses
- // variable initialization" warnings.
- {
- wuffs_gif__decoder dec;
- wuffs_base__status status = wuffs_gif__decoder__initialize(
- &dec, sizeof dec, WUFFS_VERSION,
- (hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
- : 0);
- hash >>= 1;
- if (!wuffs_base__status__is_ok(&status)) {
- ret = wuffs_base__status__message(&status);
- goto exit;
- }
-
- wuffs_base__image_config ic = ((wuffs_base__image_config){});
- status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src);
- if (!wuffs_base__status__is_ok(&status)) {
- ret = wuffs_base__status__message(&status);
- goto exit;
- }
- if (!wuffs_base__image_config__is_valid(&ic)) {
- ret = "invalid image_config";
- goto exit;
- }
-
- // 50% of the time, choose BGRA_PREMUL instead of the native pixel config.
- if (hash & 1) {
- wuffs_base__pixel_config__set(
- &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
- WUFFS_BASE__PIXEL_SUBSAMPLING__NONE,
- wuffs_base__pixel_config__width(&ic.pixcfg),
- wuffs_base__pixel_config__height(&ic.pixcfg));
- }
- hash >>= 1;
-
- // Wuffs allows either statically or dynamically allocated work buffers.
- // This program exercises dynamic allocation.
- uint64_t n = wuffs_gif__decoder__workbuf_len(&dec).max_incl;
- if (n > 64 * 1024 * 1024) { // Don't allocate more than 64 MiB.
- ret = "image too large";
- goto exit;
- }
- if (n > 0) {
- workbuf = wuffs_base__malloc_slice_u8(malloc, n);
- if (!workbuf.ptr) {
- ret = "out of memory";
- goto exit;
- }
- }
-
- n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
- if (n > 64 * 1024 * 1024) { // Don't allocate more than 64 MiB.
- ret = "image too large";
- goto exit;
- }
- if (n > 0) {
- pixbuf = wuffs_base__malloc_slice_u8(malloc, n);
- if (!pixbuf.ptr) {
- ret = "out of memory";
- goto exit;
- }
- }
-
- wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
- status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
- if (!wuffs_base__status__is_ok(&status)) {
- ret = wuffs_base__status__message(&status);
- goto exit;
- }
-
- bool seen_ok = false;
- while (true) {
- wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
- status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src);
- if (!wuffs_base__status__is_ok(&status)) {
- if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
- ret = wuffs_base__status__message(&status);
- }
- goto exit;
- }
-
- status = wuffs_gif__decoder__decode_frame(
- &dec, &pb, src, WUFFS_BASE__PIXEL_BLEND__SRC, workbuf, NULL);
-
- wuffs_base__rect_ie_u32 frame_rect =
- wuffs_base__frame_config__bounds(&fc);
- wuffs_base__rect_ie_u32 dirty_rect =
- wuffs_gif__decoder__frame_dirty_rect(&dec);
- if (!wuffs_base__rect_ie_u32__contains_rect(&frame_rect, dirty_rect)) {
- ret = "internal error: frame_rect does not contain dirty_rect";
- goto exit;
- }
-
- if (!wuffs_base__status__is_ok(&status)) {
- if ((status.repr != wuffs_base__note__end_of_data) || !seen_ok) {
- ret = wuffs_base__status__message(&status);
- }
- goto exit;
- }
- seen_ok = true;
-
- if (!wuffs_base__rect_ie_u32__equals(&frame_rect, dirty_rect)) {
- ret = "internal error: frame_rect does not equal dirty_rect";
- goto exit;
- }
- }
+ wuffs_gif__decoder dec;
+ wuffs_base__status status = wuffs_gif__decoder__initialize(
+ &dec, sizeof dec, WUFFS_VERSION,
+ (hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED : 0);
+ hash >>= 1;
+ if (!wuffs_base__status__is_ok(&status)) {
+ return wuffs_base__status__message(&status);
}
-
-exit:
- free(workbuf.ptr);
- free(pixbuf.ptr);
- return ret;
+ return fuzz_image_decoder(
+ src, hash,
+ wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(&dec));
}