xref: /aosp_15_r20/external/lz4/ossfuzz/round_trip_fuzzer.c (revision 27162e4e17433d5aa7cb38e7b6a433a09405fc7f)
1 /**
2  * This fuzz target performs a lz4 round-trip test (compress & decompress),
3  * compares the result with the original, and calls abort() on corruption.
4  */
5 
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "fuzz_helpers.h"
12 #include "lz4.h"
13 #include "fuzz_data_producer.h"
14 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)15 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
16 {
17     FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);
18     size_t const partialCapacitySeed = FUZZ_dataProducer_retrieve32(producer);
19     size = FUZZ_dataProducer_remainingBytes(producer);
20 
21     size_t const partialCapacity = FUZZ_getRange_from_uint32(partialCapacitySeed, 0, size);
22     size_t const dstCapacity = LZ4_compressBound(size);
23     size_t const largeSize = 64 * 1024 - 1;
24     size_t const smallSize = 1024;
25     char* const dstPlusLargePrefix = (char*)malloc(dstCapacity + largeSize);
26     FUZZ_ASSERT(dstPlusLargePrefix);
27     char* const dstPlusSmallPrefix = dstPlusLargePrefix + largeSize - smallSize;
28     char* const largeDict = (char*)malloc(largeSize);
29     FUZZ_ASSERT(largeDict);
30     char* const smallDict = largeDict + largeSize - smallSize;
31     char* const dst = dstPlusLargePrefix + largeSize;
32     char* const rt = (char*)malloc(size);
33     FUZZ_ASSERT(rt);
34 
35     /* Compression must succeed and round trip correctly. */
36     int const dstSize = LZ4_compress_default((const char*)data, dst,
37                                              size, dstCapacity);
38     FUZZ_ASSERT(dstSize > 0);
39 
40     int const rtSize = LZ4_decompress_safe(dst, rt, dstSize, size);
41     FUZZ_ASSERT_MSG(rtSize == size, "Incorrect size");
42     FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!");
43 
44     /* Partial decompression must succeed. */
45     {
46         char* const partial = (char*)malloc(partialCapacity);
47         FUZZ_ASSERT(partial);
48         int const partialSize = LZ4_decompress_safe_partial(
49                 dst, partial, dstSize, partialCapacity, partialCapacity);
50         FUZZ_ASSERT(partialSize >= 0);
51         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
52         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
53         free(partial);
54     }
55     /* Partial decompression using dict with no dict. */
56     {
57         char* const partial = (char*)malloc(partialCapacity);
58         FUZZ_ASSERT(partial);
59         int const partialSize = LZ4_decompress_safe_partial_usingDict(
60                 dst, partial, dstSize, partialCapacity, partialCapacity, NULL, 0);
61         FUZZ_ASSERT(partialSize >= 0);
62         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
63         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
64         free(partial);
65     }
66     /* Partial decompression using dict with small prefix as dict */
67     {
68         char* const partial = (char*)malloc(partialCapacity);
69         FUZZ_ASSERT(partial);
70         int const partialSize = LZ4_decompress_safe_partial_usingDict(
71                 dst, partial, dstSize, partialCapacity, partialCapacity, dstPlusSmallPrefix, smallSize);
72         FUZZ_ASSERT(partialSize >= 0);
73         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
74         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
75         free(partial);
76     }
77     /* Partial decompression using dict with large prefix as dict */
78     {
79         char* const partial = (char*)malloc(partialCapacity);
80         FUZZ_ASSERT(partial);
81         int const partialSize = LZ4_decompress_safe_partial_usingDict(
82                 dst, partial, dstSize, partialCapacity, partialCapacity, dstPlusLargePrefix, largeSize);
83         FUZZ_ASSERT(partialSize >= 0);
84         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
85         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
86         free(partial);
87     }
88     /* Partial decompression using dict with small external dict */
89     {
90         char* const partial = (char*)malloc(partialCapacity);
91         FUZZ_ASSERT(partial);
92         int const partialSize = LZ4_decompress_safe_partial_usingDict(
93                 dst, partial, dstSize, partialCapacity, partialCapacity, smallDict, smallSize);
94         FUZZ_ASSERT(partialSize >= 0);
95         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
96         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
97         free(partial);
98     }
99     /* Partial decompression using dict with large external dict */
100     {
101         char* const partial = (char*)malloc(partialCapacity);
102         FUZZ_ASSERT(partial);
103         int const partialSize = LZ4_decompress_safe_partial_usingDict(
104                 dst, partial, dstSize, partialCapacity, partialCapacity, largeDict, largeSize);
105         FUZZ_ASSERT(partialSize >= 0);
106         FUZZ_ASSERT_MSG(partialSize == partialCapacity, "Incorrect size");
107         FUZZ_ASSERT_MSG(!memcmp(data, partial, partialSize), "Corruption!");
108         free(partial);
109     }
110 
111     free(dstPlusLargePrefix);
112     free(largeDict);
113     free(rt);
114     FUZZ_dataProducer_free(producer);
115 
116     return 0;
117 }
118