blob: 19ab9e3acbe274228e6094f844bb7b8cf09960e4 [file] [log] [blame]
Yann Collet4856a002015-01-24 01:58:16 +01001/*
2 Fuzzer test tool for zstd
3 Copyright (C) Yann Collet 2014-2105
4
5 GPL v2 License
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 You can contact the author at :
22 - ZSTD source repository : https://github.com/Cyan4973/zstd
23 - ZSTD public forum : https://groups.google.com/forum/#!forum/lz4c
24*/
25
26/**************************************
27* Compiler specific
28**************************************/
29#ifdef _MSC_VER /* Visual Studio */
30# define _CRT_SECURE_NO_WARNINGS /* fgets */
31# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
32# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
33#endif
34
35#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
36#ifdef __GNUC__
37# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
38# pragma GCC diagnostic ignored "-Wmissing-field-initializers" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
39#endif
40
41
42/**************************************
43* Includes
44**************************************/
45#include <stdlib.h> /* free */
46#include <stdio.h> /* fgets, sscanf */
47#include <sys/timeb.h> /* timeb */
48#include <string.h> /* strcmp */
49#include "zstd_static.h"
Yann Colletd5d9bc32015-08-23 23:13:49 +010050#include "datagen.h" /* RDG_genBuffer */
Yann Collet4856a002015-01-24 01:58:16 +010051#include "xxhash.h" /* XXH64 */
52
53
54/**************************************
55* Basic Types
56**************************************/
57#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
58# include <stdint.h>
59typedef uint8_t BYTE;
60typedef uint16_t U16;
61typedef uint32_t U32;
62typedef int32_t S32;
63typedef uint64_t U64;
64#else
65typedef unsigned char BYTE;
66typedef unsigned short U16;
67typedef unsigned int U32;
68typedef signed int S32;
69typedef unsigned long long U64;
70#endif
71
72
73/**************************************
74 Constants
75**************************************/
76#ifndef ZSTD_VERSION
77# define ZSTD_VERSION ""
78#endif
79
80#define KB *(1U<<10)
81#define MB *(1U<<20)
82#define GB *(1U<<30)
83
84static const U32 nbTestsDefault = 32 KB;
85#define COMPRESSIBLE_NOISE_LENGTH (10 MB)
86#define FUZ_COMPRESSIBILITY_DEFAULT 50
87static const U32 prime1 = 2654435761U;
88static const U32 prime2 = 2246822519U;
89
90
91
92/**************************************
93* Display Macros
94**************************************/
95#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)
96#define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
97static U32 g_displayLevel = 2;
98
99#define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \
100 if ((FUZ_GetMilliSpan(g_time) > g_refreshRate) || (g_displayLevel>=4)) \
101 { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \
102 if (g_displayLevel>=4) fflush(stdout); } }
103static const U32 g_refreshRate = 150;
104static U32 g_time = 0;
105
106
107/*********************************************************
108* Fuzzer functions
109*********************************************************/
110static U32 FUZ_GetMilliStart(void)
111{
112 struct timeb tb;
113 U32 nCount;
114 ftime( &tb );
115 nCount = (U32) (((tb.time & 0xFFFFF) * 1000) + tb.millitm);
116 return nCount;
117}
118
119
120static U32 FUZ_GetMilliSpan(U32 nTimeStart)
121{
122 U32 nCurrent = FUZ_GetMilliStart();
123 U32 nSpan = nCurrent - nTimeStart;
124 if (nTimeStart > nCurrent)
125 nSpan += 0x100000 * 1000;
126 return nSpan;
127}
128
129
130# define FUZ_rotl32(x,r) ((x << r) | (x >> (32 - r)))
131unsigned int FUZ_rand(unsigned int* src)
132{
133 U32 rand32 = *src;
134 rand32 *= prime1;
135 rand32 += prime2;
136 rand32 = FUZ_rotl32(rand32, 13);
137 *src = rand32;
138 return rand32 >> 5;
139}
140
141
Yann Collet997f9ee2015-08-21 02:44:20 +0100142static unsigned FUZ_highbit32(U32 v32)
Yann Collet4856a002015-01-24 01:58:16 +0100143{
144 unsigned nbBits = 0;
145 if (v32==0) return 0;
146 while (v32)
147 {
148 v32 >>= 1;
149 nbBits ++;
150 }
151 return nbBits;
152}
Yann Collet4856a002015-01-24 01:58:16 +0100153
154
155static int basicUnitTests(U32 seed, double compressibility)
156{
157 int testResult = 0;
158 void* CNBuffer;
159 void* compressedBuffer;
160 void* decodedBuffer;
161 U32 randState = seed;
162 size_t result, cSize;
163 U32 testNb=0;
164
Yann Colletd5d9bc32015-08-23 23:13:49 +0100165 /* Create compressible test buffer */
Yann Collet4856a002015-01-24 01:58:16 +0100166 CNBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
167 compressedBuffer = malloc(ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH));
168 decodedBuffer = malloc(COMPRESSIBLE_NOISE_LENGTH);
Yann Collet94f998b2015-07-04 23:10:40 -0800169 if (!CNBuffer || !compressedBuffer || !decodedBuffer)
170 {
171 DISPLAY("Not enough memory, aborting\n");
172 testResult = 1;
173 goto _end;
174 }
Yann Colletd5d9bc32015-08-23 23:13:49 +0100175 RDG_genBuffer(CNBuffer, COMPRESSIBLE_NOISE_LENGTH, compressibility, 0., randState);
Yann Collet4856a002015-01-24 01:58:16 +0100176
Yann Colletd5d9bc32015-08-23 23:13:49 +0100177 /* Basic tests */
Yann Collet4856a002015-01-24 01:58:16 +0100178 DISPLAYLEVEL(4, "test%3i : compress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
179 result = ZSTD_compress(compressedBuffer, ZSTD_compressBound(COMPRESSIBLE_NOISE_LENGTH), CNBuffer, COMPRESSIBLE_NOISE_LENGTH);
180 if (ZSTD_isError(result)) goto _output_error;
181 cSize = result;
182 DISPLAYLEVEL(4, "OK (%u bytes : %.2f%%)\n", (U32)cSize, (double)cSize/COMPRESSIBLE_NOISE_LENGTH*100);
183
184 DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
185 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize);
186 if (ZSTD_isError(result)) goto _output_error;
187 DISPLAYLEVEL(4, "OK \n");
188
189 {
190 size_t i;
191 DISPLAYLEVEL(4, "test%3i : check decompressed result : ", testNb++);
192 for (i=0; i<COMPRESSIBLE_NOISE_LENGTH; i++)
193 {
194 if (((BYTE*)decodedBuffer)[i] != ((BYTE*)CNBuffer)[i]) goto _output_error;;
195 }
196 DISPLAYLEVEL(4, "OK \n");
197 }
198
199 DISPLAYLEVEL(4, "test%3i : decompress with 1 missing byte : ", testNb++);
200 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize-1);
201 if (!ZSTD_isError(result)) goto _output_error;
Yann Colletf4ce8912015-08-11 14:18:45 +0100202 if (result != (size_t)-ZSTD_ERROR_SrcSize) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100203 DISPLAYLEVEL(4, "OK \n");
204
205 DISPLAYLEVEL(4, "test%3i : decompress with 1 too much byte : ", testNb++);
206 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, compressedBuffer, cSize+1);
207 if (!ZSTD_isError(result)) goto _output_error;
Yann Colletf4ce8912015-08-11 14:18:45 +0100208 if (result != (size_t)-ZSTD_ERROR_SrcSize) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100209 DISPLAYLEVEL(4, "OK \n");
210
211 /* Decompression defense tests */
212 DISPLAYLEVEL(4, "test%3i : Check input length for magic number : ", testNb++);
213 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, CNBuffer, 3);
214 if (!ZSTD_isError(result)) goto _output_error;
Yann Colletf4ce8912015-08-11 14:18:45 +0100215 if (result != (size_t)-ZSTD_ERROR_SrcSize) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100216 DISPLAYLEVEL(4, "OK \n");
217
218 DISPLAYLEVEL(4, "test%3i : Check magic Number : ", testNb++);
219 ((char*)(CNBuffer))[0] = 1;
220 result = ZSTD_decompress(decodedBuffer, COMPRESSIBLE_NOISE_LENGTH, CNBuffer, 4);
221 if (!ZSTD_isError(result)) goto _output_error;
Yann Collet4856a002015-01-24 01:58:16 +0100222 DISPLAYLEVEL(4, "OK \n");
223
Yann Collet213089c2015-06-18 07:43:16 -0800224 /* long rle test */
225 {
226 size_t sampleSize = 0;
227 DISPLAYLEVEL(4, "test%3i : Long RLE test : ", testNb++);
Yann Colletd5d9bc32015-08-23 23:13:49 +0100228 RDG_genBuffer(CNBuffer, sampleSize, compressibility, 0., randState);
Yann Collet213089c2015-06-18 07:43:16 -0800229 memset((char*)CNBuffer+sampleSize, 'B', 256 KB - 1);
230 sampleSize += 256 KB - 1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100231 RDG_genBuffer((char*)CNBuffer+sampleSize, 96 KB, compressibility, 0., randState);
Yann Collet213089c2015-06-18 07:43:16 -0800232 sampleSize += 96 KB;
233 cSize = ZSTD_compress(compressedBuffer, ZSTD_compressBound(sampleSize), CNBuffer, sampleSize);
234 if (ZSTD_isError(cSize)) goto _output_error;
235 result = ZSTD_decompress(decodedBuffer, sampleSize, compressedBuffer, cSize);
236 if (ZSTD_isError(result)) goto _output_error;
237 if (result!=sampleSize) goto _output_error;
238 DISPLAYLEVEL(4, "OK \n");
239 }
240
241
242
Yann Collet4856a002015-01-24 01:58:16 +0100243_end:
244 free(CNBuffer);
245 free(compressedBuffer);
246 free(decodedBuffer);
247 return testResult;
248
249_output_error:
250 testResult = 1;
251 DISPLAY("Error detected in Unit tests ! \n");
252 goto _end;
253}
254
255
256static size_t findDiff(const void* buf1, const void* buf2, size_t max)
257{
Yann Collet213089c2015-06-18 07:43:16 -0800258 const BYTE* b1 = (const BYTE*)buf1;
259 const BYTE* b2 = (const BYTE*)buf2;
Yann Collet4856a002015-01-24 01:58:16 +0100260 size_t i;
261 for (i=0; i<max; i++)
262 {
263 if (b1[i] != b2[i]) break;
264 }
265 return i;
266}
267
268# define CHECK(cond, ...) if (cond) { DISPLAY("Error => "); DISPLAY(__VA_ARGS__); \
269 DISPLAY(" (seed %u, test nb %u) \n", seed, testNb); goto _output_error; }
270
271static const U32 maxSrcLog = 23;
272static const U32 maxSampleLog = 22;
273
274int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibility)
275{
Yann Colletd5d9bc32015-08-23 23:13:49 +0100276 BYTE* cNoiseBuffer[5];
Yann Collet4856a002015-01-24 01:58:16 +0100277 BYTE* srcBuffer;
278 BYTE* cBuffer;
279 BYTE* dstBuffer;
280 size_t srcBufferSize = (size_t)1<<maxSrcLog;
281 size_t dstBufferSize = (size_t)1<<maxSampleLog;
282 size_t cBufferSize = ZSTD_compressBound(dstBufferSize);
283 U32 result = 0;
284 U32 testNb = 0;
285 U32 coreSeed = seed, lseed = 0;
Yann Collet4856a002015-01-24 01:58:16 +0100286
287 /* allocation */
Yann Colletd5d9bc32015-08-23 23:13:49 +0100288 cNoiseBuffer[0] = (BYTE*)malloc (srcBufferSize);
289 cNoiseBuffer[1] = (BYTE*)malloc (srcBufferSize);
290 cNoiseBuffer[2] = (BYTE*)malloc (srcBufferSize);
291 cNoiseBuffer[3] = (BYTE*)malloc (srcBufferSize);
292 cNoiseBuffer[4] = (BYTE*)malloc (srcBufferSize);
Yann Collet213089c2015-06-18 07:43:16 -0800293 dstBuffer = (BYTE*)malloc (dstBufferSize);
294 cBuffer = (BYTE*)malloc (cBufferSize);
Yann Colletd5d9bc32015-08-23 23:13:49 +0100295 CHECK (!cNoiseBuffer[0] || !cNoiseBuffer[1] || !cNoiseBuffer[2] || !dstBuffer || !cBuffer,
296 "Not enough memory, fuzzer tests cancelled");
Yann Collet4856a002015-01-24 01:58:16 +0100297
Yann Colletd5d9bc32015-08-23 23:13:49 +0100298 /* Create initial samples */
299 RDG_genBuffer(cNoiseBuffer[0], srcBufferSize, 0.00, 0., coreSeed); /* pure noise */
300 RDG_genBuffer(cNoiseBuffer[1], srcBufferSize, 0.05, 0., coreSeed); /* barely compressible */
301 RDG_genBuffer(cNoiseBuffer[2], srcBufferSize, compressibility, 0., coreSeed);
302 RDG_genBuffer(cNoiseBuffer[3], srcBufferSize, 0.95, 0., coreSeed); /* highly compressible */
303 RDG_genBuffer(cNoiseBuffer[4], srcBufferSize, 1.00, 0., coreSeed); /* sparse content */
304 srcBuffer = cNoiseBuffer[2];
Yann Collet4856a002015-01-24 01:58:16 +0100305
306 /* catch up testNb */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100307 for (testNb=1; testNb < startTest; testNb++)
Yann Collet4856a002015-01-24 01:58:16 +0100308 FUZ_rand(&coreSeed);
309
310 /* test loop */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100311 for ( ; testNb <= nbTests; testNb++ )
Yann Collet4856a002015-01-24 01:58:16 +0100312 {
313 size_t sampleSize, sampleStart;
314 size_t cSize, dSize, dSupSize;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100315 U32 sampleSizeLog, buffNb;
Yann Collet4856a002015-01-24 01:58:16 +0100316 U64 crcOrig, crcDest;
317
318 /* init */
319 DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests);
320 FUZ_rand(&coreSeed);
321 lseed = coreSeed ^ prime1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100322 buffNb = FUZ_rand(&lseed) & 127;
323 if (buffNb & 7) buffNb=2;
324 else
325 {
326 buffNb >>= 3;
327 if (buffNb & 7)
328 {
329 const U32 tnb[2] = { 1, 3 };
330 buffNb = tnb[buffNb >> 3];
331 }
332 else
333 {
334 const U32 tnb[2] = { 0, 4 };
335 buffNb = tnb[buffNb >> 3];
336 }
337 }
338 srcBuffer = cNoiseBuffer[buffNb];
Yann Collet4856a002015-01-24 01:58:16 +0100339 sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog;
Yann Colletf4ce8912015-08-11 14:18:45 +0100340 sampleSize = (size_t)1 << sampleSizeLog;
Yann Collet4856a002015-01-24 01:58:16 +0100341 sampleSize += FUZ_rand(&lseed) & (sampleSize-1);
342 sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize);
343 crcOrig = XXH64(srcBuffer + sampleStart, sampleSize, 0);
344
Yann Collete9853b22015-08-07 19:07:32 +0100345 /* compression test */
Yann Collet4856a002015-01-24 01:58:16 +0100346 cSize = ZSTD_compress(cBuffer, cBufferSize, srcBuffer + sampleStart, sampleSize);
347 CHECK(ZSTD_isError(cSize), "ZSTD_compress failed");
348
Yann Colletf3cb79b2015-08-20 00:02:43 +0100349 /* compression failure test : too small dest buffer */
Yann Colletd5d9bc32015-08-23 23:13:49 +0100350 if (cSize > 3)
Yann Collete9853b22015-08-07 19:07:32 +0100351 {
352 size_t errorCode;
Yann Colletf4ce8912015-08-11 14:18:45 +0100353 const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
354 const size_t tooSmallSize = cSize - missing;
Yann Collet602834f2015-08-20 07:46:10 +0100355 static const U32 endMark = 0x4DC2B1A9;
356 U32 endCheck;
357 memcpy(dstBuffer+tooSmallSize, &endMark, 4);
358 errorCode = ZSTD_compress(dstBuffer, tooSmallSize, srcBuffer + sampleStart, sampleSize);
Yann Collete9853b22015-08-07 19:07:32 +0100359 CHECK(!ZSTD_isError(errorCode), "ZSTD_compress should have failed ! (buffer too small)");
Yann Collet602834f2015-08-20 07:46:10 +0100360 memcpy(&endCheck, dstBuffer+tooSmallSize, 4);
361 CHECK(endCheck != endMark, "ZSTD_compress : dst buffer overflow");
Yann Collete9853b22015-08-07 19:07:32 +0100362 }
363
Yann Colletf3cb79b2015-08-20 00:02:43 +0100364 /* successfull decompression tests*/
Yann Collet4856a002015-01-24 01:58:16 +0100365 dSupSize = (FUZ_rand(&lseed) & 1) ? 0 : (FUZ_rand(&lseed) & 31) + 1;
366 dSize = ZSTD_decompress(dstBuffer, sampleSize + dSupSize, cBuffer, cSize);
367 CHECK(dSize != sampleSize, "ZSTD_decompress failed (%s)", ZSTD_getErrorName(dSize));
368 crcDest = XXH64(dstBuffer, sampleSize, 0);
369 CHECK(crcOrig != crcDest, "dstBuffer corrupted (pos %u / %u)", (U32)findDiff(srcBuffer+sampleStart, dstBuffer, sampleSize), (U32)sampleSize);
Yann Colletf3cb79b2015-08-20 00:02:43 +0100370
371 /* truncated src decompression test */
372 {
373 size_t errorCode;
374 const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
375 const size_t tooSmallSize = cSize - missing;
376 void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch overflows */
Yann Colletf3cb79b2015-08-20 00:02:43 +0100377 CHECK(cBufferTooSmall == NULL, "not enough memory !");
Yann Colletd5d9bc32015-08-23 23:13:49 +0100378 memcpy(cBufferTooSmall, cBuffer, tooSmallSize);
Yann Colletf3cb79b2015-08-20 00:02:43 +0100379 errorCode = ZSTD_decompress(dstBuffer, dstBufferSize, cBufferTooSmall, tooSmallSize);
380 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed ! (truncated src buffer)");
381 free(cBufferTooSmall);
382 }
383
384 /* too small dst decompression test */
385 if (sampleSize > 3)
386 {
387 size_t errorCode;
388 const size_t missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
389 const size_t tooSmallSize = sampleSize - missing;
390 static const BYTE token = 0xA9;
391 dstBuffer[tooSmallSize] = token;
392 errorCode = ZSTD_decompress(dstBuffer, tooSmallSize, cBuffer, cSize);
393 CHECK(!ZSTD_isError(errorCode), "ZSTD_decompress should have failed : %u > %u (dst buffer too small)", (U32)errorCode, (U32)tooSmallSize);
394 CHECK(dstBuffer[tooSmallSize] != token, "ZSTD_decompress : dst buffer overflow");
395 }
Yann Collet997f9ee2015-08-21 02:44:20 +0100396
397 /* noisy src decompression test */
398 if (cSize > 6)
399 {
400 const U32 maxNbBits = FUZ_highbit32((U32)(cSize-4));
401 size_t pos = 4; /* preserve magic number (too easy to detect) */
402 U32 nbBits = FUZ_rand(&lseed) % maxNbBits;
403 size_t mask = (1<<nbBits) - 1;
404 size_t skipLength = FUZ_rand(&lseed) & mask;
405 pos += skipLength;
406
407 while (pos < cSize)
408 {
409 /* add noise */
410 size_t noiseStart, noiseLength;
411 nbBits = FUZ_rand(&lseed) % maxNbBits;
412 if (nbBits>0) nbBits--;
413 mask = (1<<nbBits) - 1;
414 noiseLength = (FUZ_rand(&lseed) & mask) + 1;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100415 if ( pos+noiseLength > cSize ) noiseLength = cSize-pos;
Yann Collet997f9ee2015-08-21 02:44:20 +0100416 noiseStart = FUZ_rand(&lseed) % (srcBufferSize - noiseLength);
417 memcpy(cBuffer + pos, srcBuffer + noiseStart, noiseLength);
418 pos += noiseLength;
419
420 /* keep some original src */
421 nbBits = FUZ_rand(&lseed) % maxNbBits;
422 mask = (1<<nbBits) - 1;
423 skipLength = FUZ_rand(&lseed) & mask;
424 pos += skipLength;
425 }
426
427 /* decompress noisy source */
428 {
Yann Colletd5d9bc32015-08-23 23:13:49 +0100429 U32 noiseSrc = FUZ_rand(&lseed) % 5;
Yann Collet997f9ee2015-08-21 02:44:20 +0100430 const U32 endMark = 0xA9B1C3D6;
431 U32 endCheck;
432 size_t errorCode;
Yann Colletd5d9bc32015-08-23 23:13:49 +0100433 srcBuffer = cNoiseBuffer[noiseSrc];
Yann Collet997f9ee2015-08-21 02:44:20 +0100434 memcpy(dstBuffer+sampleSize, &endMark, 4);
435 errorCode = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize);
436 /* result *may* be an unlikely success, but even then, it must strictly respect dest buffer boundaries */
437 CHECK((!ZSTD_isError(errorCode)) && (errorCode>sampleSize),
438 "ZSTD_decompress on noisy src : result is too large : %u > %u (dst buffer)", (U32)errorCode, (U32)sampleSize);
439 memcpy(&endCheck, dstBuffer+sampleSize, 4);
440 CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow");
441 }
442 }
Yann Collet4856a002015-01-24 01:58:16 +0100443 }
444 DISPLAY("\rAll fuzzer tests completed \n");
445
446_cleanup:
Yann Colletd5d9bc32015-08-23 23:13:49 +0100447 free(cNoiseBuffer[0]);
448 free(cNoiseBuffer[1]);
449 free(cNoiseBuffer[2]);
450 free(cNoiseBuffer[3]);
451 free(cNoiseBuffer[4]);
Yann Collet4856a002015-01-24 01:58:16 +0100452 free(cBuffer);
453 free(dstBuffer);
454 return result;
455
456_output_error:
457 result = 1;
458 goto _cleanup;
459}
460
461
462/*********************************************************
463* Command line
464*********************************************************/
465int FUZ_usage(char* programName)
466{
467 DISPLAY( "Usage :\n");
468 DISPLAY( " %s [args]\n", programName);
469 DISPLAY( "\n");
470 DISPLAY( "Arguments :\n");
471 DISPLAY( " -i# : Nb of tests (default:%u) \n", nbTestsDefault);
472 DISPLAY( " -s# : Select seed (default:prompt user)\n");
473 DISPLAY( " -t# : Select starting test number (default:0)\n");
Yann Collete9853b22015-08-07 19:07:32 +0100474 DISPLAY( " -P# : Select compressibility in %% (default:%i%%)\n", FUZ_COMPRESSIBILITY_DEFAULT);
Yann Collet4856a002015-01-24 01:58:16 +0100475 DISPLAY( " -v : verbose\n");
Yann Collete9853b22015-08-07 19:07:32 +0100476 DISPLAY( " -p : pause at the end\n");
Yann Collet4856a002015-01-24 01:58:16 +0100477 DISPLAY( " -h : display help and exit\n");
478 return 0;
479}
480
481
482int main(int argc, char** argv)
483{
484 U32 seed=0;
485 int seedset=0;
486 int argNb;
487 int nbTests = nbTestsDefault;
488 int testNb = 0;
489 int proba = FUZ_COMPRESSIBILITY_DEFAULT;
490 int result=0;
491 U32 mainPause = 0;
492 char* programName;
493
494 /* Check command line */
495 programName = argv[0];
496 for(argNb=1; argNb<argc; argNb++)
497 {
498 char* argument = argv[argNb];
499
500 if(!argument) continue; /* Protection if argument empty */
501
502 /* Handle commands. Aggregated commands are allowed */
503 if (argument[0]=='-')
504 {
505 argument++;
506
507 while (*argument!=0)
508 {
509 switch(*argument)
510 {
511 case 'h':
512 return FUZ_usage(programName);
513 case 'v':
514 argument++;
515 g_displayLevel=4;
516 break;
517 case 'q':
518 argument++;
519 g_displayLevel--;
520 break;
521 case 'p': /* pause at the end */
522 argument++;
523 mainPause = 1;
524 break;
525
526 case 'i':
527 argument++;
528 nbTests=0;
529 while ((*argument>='0') && (*argument<='9'))
530 {
531 nbTests *= 10;
532 nbTests += *argument - '0';
533 argument++;
534 }
535 break;
536
537 case 's':
538 argument++;
539 seed=0;
540 seedset=1;
541 while ((*argument>='0') && (*argument<='9'))
542 {
543 seed *= 10;
544 seed += *argument - '0';
545 argument++;
546 }
547 break;
548
549 case 't':
550 argument++;
551 testNb=0;
552 while ((*argument>='0') && (*argument<='9'))
553 {
554 testNb *= 10;
555 testNb += *argument - '0';
556 argument++;
557 }
558 break;
559
560 case 'P': /* compressibility % */
561 argument++;
562 proba=0;
563 while ((*argument>='0') && (*argument<='9'))
564 {
565 proba *= 10;
566 proba += *argument - '0';
567 argument++;
568 }
569 if (proba<0) proba=0;
570 if (proba>100) proba=100;
571 break;
572
573 default:
574 return FUZ_usage(programName);
575 }
576 }
577 }
578 }
579
580 /* Get Seed */
581 DISPLAY("Starting zstd tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), ZSTD_VERSION);
582
583 if (!seedset) seed = FUZ_GetMilliStart() % 10000;
584 DISPLAY("Seed = %u\n", seed);
585 if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba);
586
587 if (nbTests<=0) nbTests=1;
588
589 if (testNb==0) result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */
590 if (!result)
591 result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100);
592 if (mainPause)
593 {
Yann Colletb5e06dc2015-07-04 23:20:56 -0800594 int unused;
Yann Collet4856a002015-01-24 01:58:16 +0100595 DISPLAY("Press Enter \n");
Yann Colletb5e06dc2015-07-04 23:20:56 -0800596 unused = getchar();
597 (void)unused;
Yann Collet4856a002015-01-24 01:58:16 +0100598 }
599 return result;
600}