1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 2 // See https://llvm.org/LICENSE.txt for license information. 3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 4 5 // A fuzz target that consumes a Zlib-compressed input. 6 // This test verifies that we can find this bug with a custom mutator. 7 #include <cstddef> 8 #include <cstdint> 9 #include <cstdio> 10 #include <cstdlib> 11 #include <zlib.h> 12 13 // The fuzz target. 14 // Uncompress the data, crash on input starting with "FU". 15 // Good luck finding this w/o a custom mutator. :) 16 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 17 uint8_t Uncompressed[100]; 18 size_t UncompressedLen = sizeof(Uncompressed); 19 if (Z_OK != uncompress(Uncompressed, &UncompressedLen, Data, Size)) 20 return 0; 21 if (UncompressedLen < 2) return 0; 22 if (Uncompressed[0] == 'F' && Uncompressed[1] == 'U') 23 abort(); // Boom 24 return 0; 25 } 26 27 #ifdef CUSTOM_MUTATOR 28 29 // Forward-declare the libFuzzer's mutator callback. 30 extern "C" size_t 31 LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); 32 33 // The custom mutator: 34 // * deserialize the data (in this case, uncompress). 35 // * If the data doesn't deserialize, create a properly serialized dummy. 36 // * Mutate the deserialized data (in this case, just call LLVMFuzzerMutate). 37 // * Serialize the mutated data (in this case, compress). 38 extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, 39 size_t MaxSize, unsigned int Seed) { 40 uint8_t Uncompressed[100]; 41 size_t UncompressedLen = sizeof(Uncompressed); 42 size_t CompressedLen = MaxSize; 43 if (Z_OK != uncompress(Uncompressed, &UncompressedLen, Data, Size)) { 44 // The data didn't uncompress. 45 // So, it's either a broken input and we want to ignore it, 46 // or we've started fuzzing from an empty corpus and we need to supply 47 // out first properly compressed input. 48 uint8_t Dummy[] = {'H', 'i'}; 49 if (Z_OK != compress(Data, &CompressedLen, Dummy, sizeof(Dummy))) 50 return 0; 51 // fprintf(stderr, "Dummy: max %zd res %zd\n", MaxSize, CompressedLen); 52 return CompressedLen; 53 } 54 UncompressedLen = 55 LLVMFuzzerMutate(Uncompressed, UncompressedLen, sizeof(Uncompressed)); 56 if (Z_OK != compress(Data, &CompressedLen, Uncompressed, UncompressedLen)) 57 return 0; 58 return CompressedLen; 59 } 60 61 #endif // CUSTOM_MUTATOR 62