1*ae56e593SMitch Phillips #include <cstddef>
2*ae56e593SMitch Phillips #include <cstdint>
3*ae56e593SMitch Phillips #include <cstdio>
4*ae56e593SMitch Phillips #include <cstdlib>
5*ae56e593SMitch Phillips #include <vector>
6*ae56e593SMitch Phillips
7*ae56e593SMitch Phillips #include "gwp_asan/stack_trace_compressor.h"
8*ae56e593SMitch Phillips
9*ae56e593SMitch Phillips constexpr size_t kBytesForLargestVarInt = (sizeof(uintptr_t) * 8) / 7 + 1;
10*ae56e593SMitch Phillips
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)11*ae56e593SMitch Phillips extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
12*ae56e593SMitch Phillips size_t BufferSize = kBytesForLargestVarInt * Size / sizeof(uintptr_t);
13*ae56e593SMitch Phillips std::vector<uint8_t> Buffer(BufferSize);
14*ae56e593SMitch Phillips std::vector<uint8_t> Buffer2(BufferSize);
15*ae56e593SMitch Phillips
16*ae56e593SMitch Phillips // Unpack the fuzz bytes.
17*ae56e593SMitch Phillips gwp_asan::compression::unpack(Data, Size,
18*ae56e593SMitch Phillips reinterpret_cast<uintptr_t *>(Buffer2.data()),
19*ae56e593SMitch Phillips BufferSize / sizeof(uintptr_t));
20*ae56e593SMitch Phillips
21*ae56e593SMitch Phillips // Pack the fuzz bytes.
22*ae56e593SMitch Phillips size_t BytesWritten = gwp_asan::compression::pack(
23*ae56e593SMitch Phillips reinterpret_cast<const uintptr_t *>(Data), Size / sizeof(uintptr_t),
24*ae56e593SMitch Phillips Buffer.data(), BufferSize);
25*ae56e593SMitch Phillips
26*ae56e593SMitch Phillips // Unpack the compressed buffer.
27*ae56e593SMitch Phillips size_t DecodedElements = gwp_asan::compression::unpack(
28*ae56e593SMitch Phillips Buffer.data(), BytesWritten,
29*ae56e593SMitch Phillips reinterpret_cast<uintptr_t *>(Buffer2.data()),
30*ae56e593SMitch Phillips BufferSize / sizeof(uintptr_t));
31*ae56e593SMitch Phillips
32*ae56e593SMitch Phillips // Ensure that every element was encoded and decoded properly.
33*ae56e593SMitch Phillips if (DecodedElements != Size / sizeof(uintptr_t))
34*ae56e593SMitch Phillips abort();
35*ae56e593SMitch Phillips
36*ae56e593SMitch Phillips // Ensure that the compression and uncompression resulted in the same trace.
37*ae56e593SMitch Phillips const uintptr_t *FuzzPtrs = reinterpret_cast<const uintptr_t *>(Data);
38*ae56e593SMitch Phillips const uintptr_t *DecodedPtrs =
39*ae56e593SMitch Phillips reinterpret_cast<const uintptr_t *>(Buffer2.data());
40*ae56e593SMitch Phillips for (size_t i = 0; i < Size / sizeof(uintptr_t); ++i) {
41*ae56e593SMitch Phillips if (FuzzPtrs[i] != DecodedPtrs[i]) {
42*ae56e593SMitch Phillips fprintf(stderr, "FuzzPtrs[%zu] != DecodedPtrs[%zu] (0x%zx vs. 0x%zx)", i,
43*ae56e593SMitch Phillips i, FuzzPtrs[i], DecodedPtrs[i]);
44*ae56e593SMitch Phillips abort();
45*ae56e593SMitch Phillips }
46*ae56e593SMitch Phillips }
47*ae56e593SMitch Phillips
48*ae56e593SMitch Phillips return 0;
49*ae56e593SMitch Phillips }
50