127b27ec6Sopenharmony_ci/** 227b27ec6Sopenharmony_ci * This fuzz target performs a lz4 round-trip test (compress & decompress), 327b27ec6Sopenharmony_ci * compares the result with the original, and calls abort() on corruption. 427b27ec6Sopenharmony_ci */ 527b27ec6Sopenharmony_ci 627b27ec6Sopenharmony_ci#include <stddef.h> 727b27ec6Sopenharmony_ci#include <stdint.h> 827b27ec6Sopenharmony_ci#include <stdlib.h> 927b27ec6Sopenharmony_ci#include <string.h> 1027b27ec6Sopenharmony_ci 1127b27ec6Sopenharmony_ci#include "fuzz_helpers.h" 1227b27ec6Sopenharmony_ci#include "lz4.h" 1327b27ec6Sopenharmony_ci#include "fuzz_data_producer.h" 1427b27ec6Sopenharmony_ci 1527b27ec6Sopenharmony_ciint LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 1627b27ec6Sopenharmony_ci{ 1727b27ec6Sopenharmony_ci FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size); 1827b27ec6Sopenharmony_ci size_t const partialCapacitySeed = FUZZ_dataProducer_retrieve32(producer); 1927b27ec6Sopenharmony_ci size = FUZZ_dataProducer_remainingBytes(producer); 2027b27ec6Sopenharmony_ci 2127b27ec6Sopenharmony_ci size_t const partialCapacity = FUZZ_getRange_from_uint32(partialCapacitySeed, 0, size); 2227b27ec6Sopenharmony_ci size_t const dstCapacity = LZ4_compressBound(size); 2327b27ec6Sopenharmony_ci size_t const largeSize = 64 * 1024 - 1; 2427b27ec6Sopenharmony_ci size_t const smallSize = 1024; 2527b27ec6Sopenharmony_ci char* const dstPlusLargePrefix = (char*)malloc(dstCapacity + largeSize); 2627b27ec6Sopenharmony_ci FUZZ_ASSERT(dstPlusLargePrefix); 2727b27ec6Sopenharmony_ci char* const dstPlusSmallPrefix = dstPlusLargePrefix + largeSize - smallSize; 2827b27ec6Sopenharmony_ci char* const largeDict = (char*)malloc(largeSize); 2927b27ec6Sopenharmony_ci FUZZ_ASSERT(largeDict); 3027b27ec6Sopenharmony_ci char* const smallDict = largeDict + largeSize - smallSize; 3127b27ec6Sopenharmony_ci char* const dst = dstPlusLargePrefix + largeSize; 3227b27ec6Sopenharmony_ci char* const rt = (char*)malloc(size); 3327b27ec6Sopenharmony_ci FUZZ_ASSERT(rt); 3427b27ec6Sopenharmony_ci 3527b27ec6Sopenharmony_ci /* Compression must succeed and round trip correctly. */ 3627b27ec6Sopenharmony_ci int const dstSize = LZ4_compress_default((const char*)data, dst, 3727b27ec6Sopenharmony_ci size, dstCapacity); 3827b27ec6Sopenharmony_ci FUZZ_ASSERT(dstSize > 0); 3927b27ec6Sopenharmony_ci 4027b27ec6Sopenharmony_ci int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size); 4127b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size"); 4227b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!"); 4327b27ec6Sopenharmony_ci 4427b27ec6Sopenharmony_ci /* Partial decompression must succeed. */ 4527b27ec6Sopenharmony_ci { 4627b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 4727b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 4827b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial( 4927b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity); 5027b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 5127b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 5227b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 5327b27ec6Sopenharmony_ci free(partial); 5427b27ec6Sopenharmony_ci } 5527b27ec6Sopenharmony_ci /* Partial decompression using dict with no dict. */ 5627b27ec6Sopenharmony_ci { 5727b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 5827b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 5927b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial_usingDict( 6027b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity, NULL, 0); 6127b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 6227b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 6327b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 6427b27ec6Sopenharmony_ci free(partial); 6527b27ec6Sopenharmony_ci } 6627b27ec6Sopenharmony_ci /* Partial decompression using dict with small prefix as dict */ 6727b27ec6Sopenharmony_ci { 6827b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 6927b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 7027b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial_usingDict( 7127b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity, dstPlusSmallPrefix, smallSize); 7227b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 7327b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 7427b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 7527b27ec6Sopenharmony_ci free(partial); 7627b27ec6Sopenharmony_ci } 7727b27ec6Sopenharmony_ci /* Partial decompression using dict with large prefix as dict */ 7827b27ec6Sopenharmony_ci { 7927b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 8027b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 8127b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial_usingDict( 8227b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity, dstPlusLargePrefix, largeSize); 8327b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 8427b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 8527b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 8627b27ec6Sopenharmony_ci free(partial); 8727b27ec6Sopenharmony_ci } 8827b27ec6Sopenharmony_ci /* Partial decompression using dict with small external dict */ 8927b27ec6Sopenharmony_ci { 9027b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 9127b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 9227b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial_usingDict( 9327b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity, smallDict, smallSize); 9427b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 9527b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 9627b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 9727b27ec6Sopenharmony_ci free(partial); 9827b27ec6Sopenharmony_ci } 9927b27ec6Sopenharmony_ci /* Partial decompression using dict with large external dict */ 10027b27ec6Sopenharmony_ci { 10127b27ec6Sopenharmony_ci char* const partial = (char*)malloc(partialCapacity); 10227b27ec6Sopenharmony_ci FUZZ_ASSERT(partial); 10327b27ec6Sopenharmony_ci int const partialSize = LZ4_decompress_safe_partial_usingDict( 10427b27ec6Sopenharmony_ci dst, partial, dstSize, partialCapacity, partialCapacity, largeDict, largeSize); 10527b27ec6Sopenharmony_ci FUZZ_ASSERT(partialSize >= 0); 10627b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size"); 10727b27ec6Sopenharmony_ci FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!"); 10827b27ec6Sopenharmony_ci free(partial); 10927b27ec6Sopenharmony_ci } 11027b27ec6Sopenharmony_ci 11127b27ec6Sopenharmony_ci free(dstPlusLargePrefix); 11227b27ec6Sopenharmony_ci free(largeDict); 11327b27ec6Sopenharmony_ci free(rt); 11427b27ec6Sopenharmony_ci FUZZ_dataProducer_free(producer); 11527b27ec6Sopenharmony_ci 11627b27ec6Sopenharmony_ci return 0; 11727b27ec6Sopenharmony_ci} 118