summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Zern <jzern@google.com>2021-06-07 18:59:44 -0700
committerJames Zern <jzern@google.com>2021-06-23 18:53:05 -0700
commitb60d4603187e0ef0da6520c34d5ac03b142dbecf (patch)
tree1a10a35eceee16d2741ea3ffecc4270ef017d7bb
parent72fe52f623d8e8157c6969457ad2fcdb34a5ace3 (diff)
downloadlibwebp-b60d4603187e0ef0da6520c34d5ac03b142dbecf.tar.gz
advanced_api_fuzzer: add extreme config value coverage
this enables cases that might trigger overflows, but increases the risk of OOM and timeouts Bug: chromium:1196850 Change-Id: I317b5109525646731e762faa3c34ed28a27595dc
-rw-r--r--tests/fuzzer/advanced_api_fuzzer.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/tests/fuzzer/advanced_api_fuzzer.c b/tests/fuzzer/advanced_api_fuzzer.c
index da4613bb..29b1f259 100644
--- a/tests/fuzzer/advanced_api_fuzzer.c
+++ b/tests/fuzzer/advanced_api_fuzzer.c
@@ -14,10 +14,13 @@
//
////////////////////////////////////////////////////////////////////////////////
+#include <string.h>
+
#include "./fuzz_utils.h"
#include "webp/decode.h"
int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
+ int i;
WebPDecoderConfig config;
if (!WebPInitDecoderConfig(&config)) return 0;
if (WebPGetFeatures(data, size, &config.input) != VP8_STATUS_OK) return 0;
@@ -59,39 +62,53 @@ int LLVMFuzzerTestOneInput(const uint8_t* const data, size_t size) {
config.output.colorspace = (WEBP_CSP_MODE)(value % MODE_LAST);
#endif // WEBP_REDUCE_CSP
- if (size % 3) {
- // Decodes incrementally in chunks of increasing size.
- WebPIDecoder* idec = WebPIDecode(NULL, 0, &config);
- if (!idec) return 0;
- VP8StatusCode status;
- if (size & 8) {
- size_t available_size = value + 1;
- while (1) {
- if (available_size > size) available_size = size;
- status = WebPIUpdate(idec, data, available_size);
- if (status != VP8_STATUS_SUSPENDED || available_size == size) break;
- available_size *= 2;
+ for (i = 0; i < 2; ++i) {
+ if (i == 1) {
+ // Use the bitstream data to generate extreme ranges for the options. An
+ // alternative approach would be to use a custom corpus containing webp
+ // files prepended with sizeof(config.options) zeroes to allow the fuzzer
+ // to modify these independently.
+ const int data_offset = 50;
+ if (size > data_offset + sizeof(config.options)) {
+ memcpy(&config.options, data + data_offset, sizeof(config.options));
+ } else {
+ break;
}
- } else {
- // WebPIAppend expects new data and its size with each call.
- // Implemented here by simply advancing the pointer into data.
- const uint8_t* new_data = data;
- size_t new_size = value + 1;
- while (1) {
- if (new_data + new_size > data + size) {
- new_size = data + size - new_data;
+ }
+ if (size % 3) {
+ // Decodes incrementally in chunks of increasing size.
+ WebPIDecoder* idec = WebPIDecode(NULL, 0, &config);
+ if (!idec) return 0;
+ VP8StatusCode status;
+ if (size & 8) {
+ size_t available_size = value + 1;
+ while (1) {
+ if (available_size > size) available_size = size;
+ status = WebPIUpdate(idec, data, available_size);
+ if (status != VP8_STATUS_SUSPENDED || available_size == size) break;
+ available_size *= 2;
+ }
+ } else {
+ // WebPIAppend expects new data and its size with each call.
+ // Implemented here by simply advancing the pointer into data.
+ const uint8_t* new_data = data;
+ size_t new_size = value + 1;
+ while (1) {
+ if (new_data + new_size > data + size) {
+ new_size = data + size - new_data;
+ }
+ status = WebPIAppend(idec, new_data, new_size);
+ if (status != VP8_STATUS_SUSPENDED || new_size == 0) break;
+ new_data += new_size;
+ new_size *= 2;
}
- status = WebPIAppend(idec, new_data, new_size);
- if (status != VP8_STATUS_SUSPENDED || new_size == 0) break;
- new_data += new_size;
- new_size *= 2;
}
+ WebPIDelete(idec);
+ } else {
+ WebPDecode(data, size, &config);
}
- WebPIDelete(idec);
- } else {
- WebPDecode(data, size, &config);
- }
- WebPFreeDecBuffer(&config.output);
+ WebPFreeDecBuffer(&config.output);
+ }
return 0;
}