From 5f927c6333a26bc29426dbe414d1b2d83f48d32f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 5 Jul 2025 14:52:40 +0200 Subject: [PATCH] fuzzers: limit input size to 100KiB While testing larger inputs can be useful for uncovering bugs related to processing large data or inefficiencies in memory allocation, it also makes the fuzzing process slower and more fragile. Beyond the obvious slowdown, there are OOM issues and even in libFuzzer. Specifically, in fuzzer::InputCorpus::AddToCorpus, after a few hours of fuzzing, we accumulate so many inputs that memory usage exceeds our quota. This could be mitigated in other ways, such as dumping data early or shortening the fuzzing run duration. However, in practice, these huge inputs are often not very useful. This change will also encourage the fuzzer to mutate existing data rather than continually adding more bytes to input, because it give higher coverage. Which in turn will produce higher quality corpus. The 100 KiB limit could be reduced further. It's still quite large, let's see how it performs. I believe even 10 KiB might be sufficient or less. This issue is especially noticeable in the Matroska fuzzer, because we add input data there, which is bigger and sets max_len high in fuzzer itself. In a perfect world, we wouldn't need to impose such limits, but in reality, we face constraints in both memory and compute resources. I'll monitor coverage and fuzzing results after this change and adjust as needed. Unfortunately, this will discard all existing corpus entries larger than the limit, but that's expected. --- fuzzers/common.h | 2 ++ fuzzers/fuzzer_json.c | 3 +++ fuzzers/fuzzer_load.c | 3 +++ fuzzers/fuzzer_loadfile_direct.c | 3 +++ fuzzers/fuzzer_set_property.c | 3 +++ 5 files changed, 14 insertions(+) diff --git a/fuzzers/common.h b/fuzzers/common.h index e7c29966a4..33a8424862 100644 --- a/fuzzers/common.h +++ b/fuzzers/common.h @@ -25,6 +25,8 @@ #include +#define MAX_FUZZ_SIZE (100 << 10) // 100 KiB + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); #define MPV_STRINGIFY_(X) #X diff --git a/fuzzers/fuzzer_json.c b/fuzzers/fuzzer_json.c index 1723a68cc2..b8e01373b1 100644 --- a/fuzzers/fuzzer_json.c +++ b/fuzzers/fuzzer_json.c @@ -22,6 +22,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > MAX_FUZZ_SIZE) + return 0; + void *tmp = talloc_new(NULL); char *s = talloc_array_ptrtype(tmp, s, size + 1); memcpy(s, data, size); diff --git a/fuzzers/fuzzer_load.c b/fuzzers/fuzzer_load.c index 39075fb90f..db3b192075 100644 --- a/fuzzers/fuzzer_load.c +++ b/fuzzers/fuzzer_load.c @@ -27,6 +27,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > MAX_FUZZ_SIZE) + return 0; + #ifdef MPV_LOAD_CONFIG_FILE // config file size limit, see m_config_parse_config_file() if (size > 1000000000) diff --git a/fuzzers/fuzzer_loadfile_direct.c b/fuzzers/fuzzer_loadfile_direct.c index be2fb1110d..f12134f22f 100644 --- a/fuzzers/fuzzer_loadfile_direct.c +++ b/fuzzers/fuzzer_loadfile_direct.c @@ -24,6 +24,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > MAX_FUZZ_SIZE) + return 0; + if (size <= 1 || data[size - 1] != '\0') return 0; diff --git a/fuzzers/fuzzer_set_property.c b/fuzzers/fuzzer_set_property.c index 04bda40623..f5c17c342a 100644 --- a/fuzzers/fuzzer_set_property.c +++ b/fuzzers/fuzzer_set_property.c @@ -19,6 +19,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > MAX_FUZZ_SIZE) + return 0; + size_t value_len; switch (MPV_FORMAT) {