]> git.proxmox.com Git - ceph.git/blob - ceph/src/zstd/tests/fuzz/stream_round_trip.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / zstd / tests / fuzz / stream_round_trip.c
1 /*
2 * Copyright (c) 2016-present, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 */
9
10 /**
11 * This fuzz target performs a zstd round-trip test (compress & decompress),
12 * compares the result with the original, and calls abort() on corruption.
13 */
14
15 #define ZSTD_STATIC_LINKING_ONLY
16
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include "fuzz_helpers.h"
22 #include "zstd_helpers.h"
23
24 ZSTD_CCtx *cctx = NULL;
25 static ZSTD_DCtx *dctx = NULL;
26 static uint8_t* cBuf = NULL;
27 static uint8_t* rBuf = NULL;
28 static size_t bufSize = 0;
29 static uint32_t seed;
30
31 static ZSTD_outBuffer makeOutBuffer(uint8_t *dst, size_t capacity)
32 {
33 ZSTD_outBuffer buffer = { dst, 0, 0 };
34
35 FUZZ_ASSERT(capacity > 0);
36 buffer.size = (FUZZ_rand(&seed) % capacity) + 1;
37 FUZZ_ASSERT(buffer.size <= capacity);
38
39 return buffer;
40 }
41
42 static ZSTD_inBuffer makeInBuffer(const uint8_t **src, size_t *size)
43 {
44 ZSTD_inBuffer buffer = { *src, 0, 0 };
45
46 FUZZ_ASSERT(*size > 0);
47 buffer.size = (FUZZ_rand(&seed) % *size) + 1;
48 FUZZ_ASSERT(buffer.size <= *size);
49 *src += buffer.size;
50 *size -= buffer.size;
51
52 return buffer;
53 }
54
55 static size_t compress(uint8_t *dst, size_t capacity,
56 const uint8_t *src, size_t srcSize)
57 {
58 size_t dstSize = 0;
59 ZSTD_CCtx_reset(cctx);
60 FUZZ_setRandomParameters(cctx, srcSize, &seed);
61
62 while (srcSize > 0) {
63 ZSTD_inBuffer in = makeInBuffer(&src, &srcSize);
64 /* Mode controls the action. If mode == -1 we pick a new mode */
65 int mode = -1;
66 while (in.pos < in.size) {
67 ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
68 /* Previous action finished, pick a new mode. */
69 if (mode == -1) mode = FUZZ_rand(&seed) % 10;
70 switch (mode) {
71 case 0: /* fall-though */
72 case 1: /* fall-though */
73 case 2: {
74 size_t const ret =
75 ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_flush);
76 FUZZ_ZASSERT(ret);
77 if (ret == 0)
78 mode = -1;
79 break;
80 }
81 case 3: {
82 size_t ret =
83 ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end);
84 FUZZ_ZASSERT(ret);
85 /* Reset the compressor when the frame is finished */
86 if (ret == 0) {
87 ZSTD_CCtx_reset(cctx);
88 if ((FUZZ_rand(&seed) & 7) == 0) {
89 size_t const remaining = in.size - in.pos;
90 FUZZ_setRandomParameters(cctx, remaining, &seed);
91 }
92 mode = -1;
93 }
94 break;
95 }
96 default: {
97 size_t const ret =
98 ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_continue);
99 FUZZ_ZASSERT(ret);
100 mode = -1;
101 }
102 }
103 dst += out.pos;
104 dstSize += out.pos;
105 capacity -= out.pos;
106 }
107 }
108 for (;;) {
109 ZSTD_inBuffer in = {NULL, 0, 0};
110 ZSTD_outBuffer out = makeOutBuffer(dst, capacity);
111 size_t const ret = ZSTD_compress_generic(cctx, &out, &in, ZSTD_e_end);
112 FUZZ_ZASSERT(ret);
113
114 dst += out.pos;
115 dstSize += out.pos;
116 capacity -= out.pos;
117 if (ret == 0)
118 break;
119 }
120 return dstSize;
121 }
122
123 int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
124 {
125 size_t neededBufSize;
126
127 seed = FUZZ_seed(&src, &size);
128 neededBufSize = ZSTD_compressBound(size) * 2;
129
130 /* Allocate all buffers and contexts if not already allocated */
131 if (neededBufSize > bufSize) {
132 free(cBuf);
133 free(rBuf);
134 cBuf = (uint8_t*)malloc(neededBufSize);
135 rBuf = (uint8_t*)malloc(neededBufSize);
136 bufSize = neededBufSize;
137 FUZZ_ASSERT(cBuf && rBuf);
138 }
139 if (!cctx) {
140 cctx = ZSTD_createCCtx();
141 FUZZ_ASSERT(cctx);
142 }
143 if (!dctx) {
144 dctx = ZSTD_createDCtx();
145 FUZZ_ASSERT(dctx);
146 }
147
148 {
149 size_t const cSize = compress(cBuf, neededBufSize, src, size);
150 size_t const rSize =
151 ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize);
152 FUZZ_ZASSERT(rSize);
153 FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
154 FUZZ_ASSERT_MSG(!memcmp(src, rBuf, size), "Corruption!");
155 }
156
157 #ifndef STATEFUL_FUZZING
158 ZSTD_freeCCtx(cctx); cctx = NULL;
159 ZSTD_freeDCtx(dctx); dctx = NULL;
160 #endif
161 return 0;
162 }