| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| // A fuzz target that consumes a Zlib-compressed input. |
| // This test verifies that we can find this bug with a custom mutator. |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstdlib> |
| #include <zlib.h> |
| |
| // The fuzz target. |
| // Uncompress the data, crash on input starting with "FU". |
| // Good luck finding this w/o a custom mutator. :) |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { |
| uint8_t Uncompressed[100]; |
| size_t UncompressedLen = sizeof(Uncompressed); |
| if (Z_OK != uncompress(Uncompressed, &UncompressedLen, Data, Size)) |
| return 0; |
| if (UncompressedLen < 2) return 0; |
| if (Uncompressed[0] == 'F' && Uncompressed[1] == 'U') |
| abort(); // Boom |
| return 0; |
| } |
| |
| #ifdef CUSTOM_MUTATOR |
| |
| // Forward-declare the libFuzzer's mutator callback. |
| extern "C" size_t |
| LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); |
| |
| // The custom mutator: |
| // * deserialize the data (in this case, uncompress). |
| // * If the data doesn't deserialize, create a properly serialized dummy. |
| // * Mutate the deserialized data (in this case, just call LLVMFuzzerMutate). |
| // * Serialize the mutated data (in this case, compress). |
| extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, |
| size_t MaxSize, unsigned int Seed) { |
| uint8_t Uncompressed[100]; |
| size_t UncompressedLen = sizeof(Uncompressed); |
| size_t CompressedLen = MaxSize; |
| if (Z_OK != uncompress(Uncompressed, &UncompressedLen, Data, Size)) { |
| // The data didn't uncompress. |
| // So, it's either a broken input and we want to ignore it, |
| // or we've started fuzzing from an empty corpus and we need to supply |
| // out first properly compressed input. |
| uint8_t Dummy[] = {'H', 'i'}; |
| if (Z_OK != compress(Data, &CompressedLen, Dummy, sizeof(Dummy))) |
| return 0; |
| // fprintf(stderr, "Dummy: max %zd res %zd\n", MaxSize, CompressedLen); |
| return CompressedLen; |
| } |
| UncompressedLen = |
| LLVMFuzzerMutate(Uncompressed, UncompressedLen, sizeof(Uncompressed)); |
| if (Z_OK != compress(Data, &CompressedLen, Uncompressed, UncompressedLen)) |
| return 0; |
| return CompressedLen; |
| } |
| |
| #endif // CUSTOM_MUTATOR |