~mmach/netext73/lz4

« back to all changes in this revision

Viewing changes to ossfuzz/round_trip_frame_uncompressed_fuzzer.c

  • Committer: mmach
  • Date: 2022-11-09 18:52:10 UTC
  • Revision ID: netbit73@gmail.com-20221109185210-w358idlhh0phq688
1.9.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_data_producer.h"
 
12
#include "fuzz_helpers.h"
 
13
#include "lz4.h"
 
14
#include "lz4_helpers.h"
 
15
#include "lz4frame.h"
 
16
#include "lz4frame_static.h"
 
17
 
 
18
static void decompress(LZ4F_dctx *dctx, void *src, void *dst,
 
19
                       size_t dstCapacity, size_t readSize) {
 
20
    size_t ret = 1;
 
21
    const void *srcPtr = (const char *) src;
 
22
    void *dstPtr = (char *) dst;
 
23
    const void *const srcEnd = (const char *) srcPtr + readSize;
 
24
 
 
25
    while (ret != 0) {
 
26
        while (srcPtr < srcEnd && ret != 0) {
 
27
            /* Any data within dst has been flushed at this stage */
 
28
            size_t dstSize = dstCapacity;
 
29
            size_t srcSize = (const char *) srcEnd - (const char *) srcPtr;
 
30
            ret = LZ4F_decompress(dctx, dstPtr, &dstSize, srcPtr, &srcSize,
 
31
                    /* LZ4F_decompressOptions_t */ NULL);
 
32
            FUZZ_ASSERT(!LZ4F_isError(ret));
 
33
 
 
34
            /* Update input */
 
35
            srcPtr = (const char *) srcPtr + srcSize;
 
36
            dstPtr = (char *) dstPtr + dstSize;
 
37
        }
 
38
 
 
39
        FUZZ_ASSERT(srcPtr <= srcEnd);
 
40
    }
 
41
}
 
42
 
 
43
static void compress_round_trip(const uint8_t *data, size_t size,
 
44
                                FUZZ_dataProducer_t *producer, LZ4F_preferences_t const prefs) {
 
45
 
 
46
    // Choose random uncompressed offset start and end by producing seeds from random data, calculate the remaining
 
47
    // data size that will be used for compression later and use the seeds to actually calculate the offsets
 
48
    size_t const uncompressedOffsetSeed = FUZZ_dataProducer_retrieve32(producer);
 
49
    size_t const uncompressedEndOffsetSeed = FUZZ_dataProducer_retrieve32(producer);
 
50
    size = FUZZ_dataProducer_remainingBytes(producer);
 
51
 
 
52
    size_t const uncompressedOffset = FUZZ_getRange_from_uint32(uncompressedOffsetSeed, 0, size);
 
53
    size_t const uncompressedEndOffset = FUZZ_getRange_from_uint32(uncompressedEndOffsetSeed, uncompressedOffset, size);
 
54
    size_t const uncompressedSize = uncompressedEndOffset - uncompressedOffset;
 
55
    FUZZ_ASSERT(uncompressedOffset <= uncompressedEndOffset);
 
56
    FUZZ_ASSERT(uncompressedEndOffset <= size);
 
57
 
 
58
    const uint8_t *const uncompressedData = data + uncompressedOffset;
 
59
 
 
60
    size_t const dstCapacity =
 
61
            LZ4F_compressFrameBound(LZ4_compressBound(size), &prefs) +
 
62
            uncompressedSize;
 
63
    char *const dst = (char *) malloc(dstCapacity);
 
64
    size_t rtCapacity = dstCapacity;
 
65
    char *const rt = (char *) malloc(rtCapacity);
 
66
 
 
67
    FUZZ_ASSERT(dst);
 
68
    FUZZ_ASSERT(rt);
 
69
 
 
70
    /* Compression must succeed and round trip correctly. */
 
71
    LZ4F_compressionContext_t ctx;
 
72
    size_t const ctxCreation = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
 
73
    FUZZ_ASSERT(!LZ4F_isError(ctxCreation));
 
74
 
 
75
    size_t const headerSize = LZ4F_compressBegin(ctx, dst, dstCapacity, &prefs);
 
76
    FUZZ_ASSERT(!LZ4F_isError(headerSize));
 
77
    size_t compressedSize = headerSize;
 
78
 
 
79
    /* Compress data before uncompressed offset */
 
80
    size_t lz4Return = LZ4F_compressUpdate(ctx, dst + compressedSize, dstCapacity,
 
81
                                           data, uncompressedOffset, NULL);
 
82
    FUZZ_ASSERT(!LZ4F_isError(lz4Return));
 
83
    compressedSize += lz4Return;
 
84
 
 
85
    /* Add uncompressed data */
 
86
    lz4Return = LZ4F_uncompressedUpdate(ctx, dst + compressedSize, dstCapacity,
 
87
                                        uncompressedData, uncompressedSize, NULL);
 
88
    FUZZ_ASSERT(!LZ4F_isError(lz4Return));
 
89
    compressedSize += lz4Return;
 
90
 
 
91
    /* Compress data after uncompressed offset */
 
92
    lz4Return = LZ4F_compressUpdate(ctx, dst + compressedSize, dstCapacity,
 
93
                                    data + uncompressedEndOffset,
 
94
                                    size - uncompressedEndOffset, NULL);
 
95
    FUZZ_ASSERT(!LZ4F_isError(lz4Return));
 
96
    compressedSize += lz4Return;
 
97
 
 
98
    /* Finish compression */
 
99
    lz4Return = LZ4F_compressEnd(ctx, dst + compressedSize, dstCapacity, NULL);
 
100
    FUZZ_ASSERT(!LZ4F_isError(lz4Return));
 
101
    compressedSize += lz4Return;
 
102
 
 
103
    LZ4F_decompressOptions_t opts;
 
104
    memset(&opts, 0, sizeof(opts));
 
105
    opts.stableDst = 1;
 
106
    LZ4F_dctx *dctx;
 
107
    LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
 
108
    FUZZ_ASSERT(dctx);
 
109
 
 
110
    decompress(dctx, dst, rt, rtCapacity, compressedSize);
 
111
 
 
112
    LZ4F_freeDecompressionContext(dctx);
 
113
 
 
114
    FUZZ_ASSERT_MSG(!memcmp(data, rt, size), "Corruption!");
 
115
 
 
116
    free(dst);
 
117
    free(rt);
 
118
 
 
119
    FUZZ_dataProducer_free(producer);
 
120
    LZ4F_freeCompressionContext(ctx);
 
121
}
 
122
 
 
123
static void compress_independent_block_mode(const uint8_t *data, size_t size) {
 
124
    FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(data, size);
 
125
    LZ4F_preferences_t prefs = FUZZ_dataProducer_preferences(producer);
 
126
    prefs.frameInfo.blockMode = LZ4F_blockIndependent;
 
127
    compress_round_trip(data, size, producer, prefs);
 
128
}
 
129
 
 
130
 
 
131
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
132
    compress_independent_block_mode(data, size);
 
133
    return 0;
 
134
}