/src/c-blosc2/tests/fuzz/fuzz_compress_frame.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <stdint.h> |
2 | | #include <stdlib.h> |
3 | | #include <stdio.h> |
4 | | #include <inttypes.h> |
5 | | |
6 | | #include <blosc2.h> |
7 | | |
8 | | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
9 | | |
10 | | #ifdef __cplusplus |
11 | | extern "C" { |
12 | | #endif |
13 | | |
14 | 2.29k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
15 | 2.29k | const char *const compressors[] = { "blosclz", "lz4", "lz4hc", "zlib", "zstd" }; |
16 | 2.29k | int32_t i = 0, dsize = 0, filter = BLOSC_BITSHUFFLE; |
17 | 2.29k | int32_t nchunk = 0, max_chunksize = 512; |
18 | 2.29k | int64_t nchunks = 0; |
19 | | |
20 | 2.29k | blosc2_init(); |
21 | | |
22 | 2.29k | blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS; |
23 | 2.29k | cparams.typesize = 1; |
24 | | /* Find next available compressor */ |
25 | 2.29k | cparams.compcode = 0; |
26 | 2.29k | while (blosc1_set_compressor(compressors[cparams.compcode % 6]) == -1 && i < 6) { |
27 | 0 | cparams.compcode++, i++; |
28 | 0 | } |
29 | 2.29k | if (i == 6) { |
30 | | /* No compressors available */ |
31 | 0 | blosc2_destroy(); |
32 | 0 | return 0; |
33 | 0 | } |
34 | 2.29k | if (size > INT32_MAX) { |
35 | 0 | printf("Conversion error: size_t does not fit in int32_t\n"); |
36 | 0 | return 0; |
37 | 0 | } |
38 | 2.29k | if (size > 0) { |
39 | | /* Variable size compression level and max chunksize */ |
40 | 2.29k | cparams.clevel = data[0] % (9 + 1); |
41 | 2.29k | max_chunksize *= data[0]; |
42 | 2.29k | } |
43 | 2.29k | if (size > 1) { |
44 | 2.27k | filter = data[1]; |
45 | 2.27k | } |
46 | 2.29k | cparams.filters[BLOSC2_MAX_FILTERS - 1] = filter % (BLOSC_BITSHUFFLE + 1); |
47 | 2.29k | cparams.filters_meta[BLOSC2_MAX_FILTERS - 1] = filter; |
48 | 2.29k | cparams.nthreads = 1; |
49 | | |
50 | 2.29k | blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS; |
51 | 2.29k | dparams.nthreads = 1; |
52 | | |
53 | | /* Create a super-chunk backed by an in-memory frame */ |
54 | 2.29k | blosc2_storage storage = {.cparams=&cparams, .dparams=&dparams}; |
55 | 2.29k | blosc2_schunk* schunk = blosc2_schunk_new(&storage); |
56 | 2.29k | if (schunk == NULL) { |
57 | 0 | blosc2_destroy(); |
58 | 0 | return 0; |
59 | 0 | } |
60 | | |
61 | | /* Compress data */ |
62 | 2.29k | int32_t chunksize = max_chunksize; |
63 | 43.9k | for (i = 0; chunksize > 0 && i < (int32_t)size; i += chunksize, nchunks++) { |
64 | 41.6k | if (i + chunksize > (int32_t)size) |
65 | 2.08k | chunksize = (int32_t)size - i; |
66 | 41.6k | nchunks = blosc2_schunk_append_buffer(schunk, (uint8_t *)data + i, chunksize); |
67 | 41.6k | if (nchunks < 0) { |
68 | 0 | printf("Compression error. Error code: %" PRId64 "\n", nchunks); |
69 | 0 | break; |
70 | 0 | } |
71 | 41.6k | } |
72 | | |
73 | | /* Decompress data */ |
74 | 2.29k | uint8_t *uncompressed_data = (uint8_t *)malloc(size+1); |
75 | 2.29k | if (uncompressed_data != NULL) { |
76 | 15.7k | for (i = 0, nchunk = 0; nchunk < nchunks-1; nchunk++) { |
77 | 13.8k | dsize = blosc2_schunk_decompress_chunk(schunk, nchunk, uncompressed_data + i, chunksize); |
78 | 13.8k | if (dsize < 0) { |
79 | 416 | printf("Decompression error. Error code: %d\n", dsize); |
80 | 416 | break; |
81 | 416 | } |
82 | 13.4k | i += dsize; |
83 | 13.4k | } |
84 | | |
85 | | /* Compare decompressed data with original */ |
86 | 2.29k | if (size > 0 && nchunks > 0) { |
87 | 2.29k | if (dsize < 0 || memcmp(data, uncompressed_data, size) != 0) { |
88 | 416 | printf("Decompression data does not match original %d\n", dsize); |
89 | 416 | } |
90 | 2.29k | } |
91 | | |
92 | 2.29k | free(uncompressed_data); |
93 | 2.29k | } |
94 | | |
95 | | /* Free resources */ |
96 | 2.29k | blosc2_schunk_free(schunk); |
97 | | |
98 | 2.29k | blosc2_destroy(); |
99 | 2.29k | return 0; |
100 | 2.29k | } |
101 | | |
102 | | #ifdef __cplusplus |
103 | | } |
104 | | #endif |