2013-12-30 17:16:52 +00:00
/*
2014-12-10 08:05:44 +00:00
fuzzer . c - Fuzzer test tool for LZ4
2017-03-16 22:10:38 +00:00
Copyright ( C ) Yann Collet 2012 - 2017
2014-12-10 08:05:44 +00:00
GPL v2 License
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License along
with this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
You can contact the author at :
2016-06-29 19:48:27 +00:00
- LZ4 homepage : http : //www.lz4.org
2016-11-03 14:12:57 +00:00
- LZ4 source repo : https : //github.com/lz4/lz4
2013-12-30 17:16:52 +00:00
*/
2016-06-29 19:48:27 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Compiler options
2014-04-28 20:45:35 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-02 21:03:58 +00:00
# ifdef _MSC_VER /* Visual Studio */
2016-12-21 15:10:09 +00:00
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
2014-12-10 08:05:44 +00:00
# pragma warning(disable : 4146) /* disable: C4146: minus unsigned expression */
# pragma warning(disable : 4310) /* disable: C4310: constant char value > 127 */
2014-07-02 21:03:58 +00:00
# endif
2013-12-30 17:16:52 +00:00
2018-03-21 14:14:13 +00:00
2016-06-29 19:48:27 +00:00
/*-************************************
2016-11-13 01:14:57 +00:00
* Dependencies
2014-04-28 20:45:35 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-06-01 18:52:22 +00:00
# if defined(__unix__) && !defined(_AIX) /* must be included before platform.h for MAP_ANONYMOUS */
2019-04-05 18:55:34 +00:00
# undef _GNU_SOURCE /* in case it's already defined */
2019-04-05 18:47:06 +00:00
# define _GNU_SOURCE /* MAP_ANONYMOUS even in -std=c99 mode */
2018-03-21 14:14:13 +00:00
# include <sys / mman.h> /* mmap */
# endif
2016-12-21 15:10:09 +00:00
# include "platform.h" /* _CRT_SECURE_NO_WARNINGS */
2016-12-21 08:44:59 +00:00
# include "util.h" /* U32 */
2013-12-30 17:16:52 +00:00
# include <stdlib.h>
2014-12-10 08:05:44 +00:00
# include <stdio.h> /* fgets, sscanf */
# include <string.h> /* strcmp */
2016-09-03 02:48:24 +00:00
# include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
2018-05-02 19:56:37 +00:00
# include <assert.h>
2019-01-09 20:09:52 +00:00
# include <limits.h> /* INT_MAX */
2018-06-01 18:52:22 +00:00
2019-04-17 16:20:09 +00:00
# if defined(_AIX)
# include <sys / mman.h> /* mmap */
# endif
2019-04-04 19:47:36 +00:00
# define LZ4_DISABLE_DEPRECATE_WARNINGS /* LZ4_decompress_fast */
2018-04-12 22:23:01 +00:00
# define LZ4_STATIC_LINKING_ONLY
2019-04-04 19:47:36 +00:00
# include "lz4.h"
2017-03-16 09:16:24 +00:00
# define LZ4_HC_STATIC_LINKING_ONLY
2013-12-30 17:16:52 +00:00
# include "lz4hc.h"
2016-06-29 19:48:27 +00:00
# define XXH_STATIC_LINKING_ONLY
2014-04-28 20:45:35 +00:00
# include "xxhash.h"
2016-12-21 09:39:27 +00:00
/*-************************************
* Basic Types
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if !defined(__cplusplus) && !(defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ )
typedef size_t uintptr_t ; /* true on most systems, except OpenVMS-64 (which doesn't need address overflow test) */
# endif
2016-08-10 07:14:11 +00:00
/*-************************************
2015-03-07 18:30:45 +00:00
* Constants
2014-04-28 20:45:35 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-04-22 23:54:32 +00:00
# define NB_ATTEMPTS (1<<16)
2014-04-28 20:45:35 +00:00
# define COMPRESSIBLE_NOISE_LENGTH (1 << 21)
# define FUZ_MAX_BLOCK_SIZE (1 << 17)
# define FUZ_MAX_DICT_SIZE (1 << 15)
2014-12-10 08:05:44 +00:00
# define FUZ_COMPRESSIBILITY_DEFAULT 60
2013-12-30 17:16:52 +00:00
# define PRIME1 2654435761U
# define PRIME2 2246822519U
# define PRIME3 3266489917U
2014-07-02 08:38:34 +00:00
# define KB *(1U<<10)
# define MB *(1U<<20)
# define GB *(1U<<30)
2016-08-10 07:14:11 +00:00
/*-***************************************
2015-03-07 18:30:45 +00:00
* Macros
2014-08-30 11:32:09 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-11-13 01:14:57 +00:00
# define DISPLAY(...) fprintf(stdout, __VA_ARGS__)
2014-10-18 12:27:32 +00:00
# define DISPLAYLEVEL(l, ...) if (g_displayLevel>=l) { DISPLAY(__VA_ARGS__); }
static int g_displayLevel = 2 ;
2016-11-13 01:14:57 +00:00
# define MIN(a,b) ( (a) < (b) ? (a) : (b) )
2014-04-29 20:39:08 +00:00
2016-08-10 07:14:11 +00:00
/*-*******************************************************
2015-03-07 18:30:45 +00:00
* Fuzzer functions
2014-04-28 20:45:35 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-09-03 02:48:24 +00:00
static clock_t FUZ_GetClockSpan ( clock_t clockStart )
2013-12-30 17:16:52 +00:00
{
2016-09-03 02:48:24 +00:00
return clock ( ) - clockStart ; /* works even if overflow; max span ~ 30mn */
2013-12-30 17:16:52 +00:00
}
2016-11-13 01:14:57 +00:00
static void FUZ_displayUpdate ( unsigned testNb )
{
static clock_t g_time = 0 ;
static const clock_t g_refreshRate = CLOCKS_PER_SEC / 5 ;
if ( ( FUZ_GetClockSpan ( g_time ) > g_refreshRate ) | | ( g_displayLevel > = 4 ) ) {
g_time = clock ( ) ;
DISPLAY ( " \r %5u " , testNb ) ;
fflush ( stdout ) ;
}
}
2014-10-19 12:47:22 +00:00
static U32 FUZ_rotl32 ( U32 u32 , U32 nbBits )
{
return ( ( u32 < < nbBits ) | ( u32 > > ( 32 - nbBits ) ) ) ;
}
2019-06-29 03:15:43 +00:00
static U32 FUZ_highbit32 ( U32 v32 )
{
unsigned nbBits = 0 ;
if ( v32 = = 0 ) return 0 ;
2019-06-29 03:55:47 +00:00
while ( v32 ) { v32 > > = 1 ; nbBits + + ; }
2019-06-29 03:15:43 +00:00
return nbBits ;
}
2014-10-19 12:47:22 +00:00
static U32 FUZ_rand ( U32 * src )
2013-12-30 17:16:52 +00:00
{
2014-04-28 22:49:31 +00:00
U32 rand32 = * src ;
rand32 * = PRIME1 ;
2015-04-24 09:15:12 +00:00
rand32 ^ = PRIME2 ;
2014-04-28 22:49:31 +00:00
rand32 = FUZ_rotl32 ( rand32 , 13 ) ;
* src = rand32 ;
2015-04-24 09:15:12 +00:00
return rand32 ;
2013-12-30 17:16:52 +00:00
}
2014-04-28 20:45:35 +00:00
# define FUZ_RAND15BITS ((FUZ_rand(seed) >> 3) & 32767)
2014-08-30 11:32:09 +00:00
# define FUZ_RANDLENGTH ( ((FUZ_rand(seed) >> 7) & 3) ? (FUZ_rand(seed) % 15) : (FUZ_rand(seed) % 510) + 15)
2014-12-10 08:05:44 +00:00
static void FUZ_fillCompressibleNoiseBuffer ( void * buffer , size_t bufferSize , double proba , U32 * seed )
2013-12-30 17:16:52 +00:00
{
2016-11-13 01:14:57 +00:00
BYTE * const BBuffer = ( BYTE * ) buffer ;
2014-12-10 08:05:44 +00:00
size_t pos = 0 ;
2016-11-13 01:14:57 +00:00
U32 const P32 = ( U32 ) ( 32768 * proba ) ;
2014-04-28 20:45:35 +00:00
2015-04-24 09:15:12 +00:00
/* First Bytes */
while ( pos < 20 )
BBuffer [ pos + + ] = ( BYTE ) ( FUZ_rand ( seed ) ) ;
2014-04-28 20:45:35 +00:00
2016-11-13 01:14:57 +00:00
while ( pos < bufferSize ) {
2015-04-24 09:15:12 +00:00
/* Select : Literal (noise) or copy (within 64K) */
2016-11-13 01:14:57 +00:00
if ( FUZ_RAND15BITS < P32 ) {
2015-04-24 09:15:12 +00:00
/* Copy (within 64K) */
2019-04-13 00:40:23 +00:00
size_t const length = ( size_t ) FUZ_RANDLENGTH + 4 ;
2016-11-13 01:14:57 +00:00
size_t const d = MIN ( pos + length , bufferSize ) ;
size_t match ;
2019-04-13 00:40:23 +00:00
size_t offset = ( size_t ) FUZ_RAND15BITS + 1 ;
2015-04-24 09:15:12 +00:00
while ( offset > pos ) offset > > = 1 ;
2014-12-10 08:05:44 +00:00
match = pos - offset ;
while ( pos < d ) BBuffer [ pos + + ] = BBuffer [ match + + ] ;
2016-11-13 01:14:57 +00:00
} else {
2015-04-24 09:15:12 +00:00
/* Literal (noise) */
2016-11-13 01:14:57 +00:00
size_t const length = FUZ_RANDLENGTH ;
size_t const d = MIN ( pos + length , bufferSize ) ;
2014-04-28 20:45:35 +00:00
while ( pos < d ) BBuffer [ pos + + ] = ( BYTE ) ( FUZ_rand ( seed ) > > 5 ) ;
}
}
2013-12-30 17:16:52 +00:00
}
2014-07-02 17:02:29 +00:00
# define MAX_NB_BUFF_I134 150
2014-07-05 11:50:05 +00:00
# define BLOCKSIZE_I134 (32 MB)
2016-08-11 10:18:45 +00:00
/*! FUZ_AddressOverflow() :
* Aggressively pushes memory allocation limits ,
* and generates patterns which create address space overflow .
* only possible in 32 - bits mode */
2014-10-10 19:58:42 +00:00
static int FUZ_AddressOverflow ( void )
2014-07-02 08:38:34 +00:00
{
2015-03-15 00:42:27 +00:00
char * buffers [ MAX_NB_BUFF_I134 + 1 ] ;
2016-11-17 21:02:06 +00:00
int nbBuff = 0 ;
2014-10-25 19:52:10 +00:00
int highAddress = 0 ;
2014-07-02 08:38:34 +00:00
2015-06-29 08:31:41 +00:00
DISPLAY ( " Overflow tests : " ) ;
2014-07-02 08:38:34 +00:00
2015-04-10 22:42:17 +00:00
/* Only possible in 32-bits */
2016-11-13 01:14:57 +00:00
if ( sizeof ( void * ) = = 8 ) {
2015-06-29 08:31:41 +00:00
DISPLAY ( " 64 bits mode : no overflow \n " ) ;
2014-07-05 11:50:05 +00:00
fflush ( stdout ) ;
2014-10-25 19:52:10 +00:00
return 0 ;
2014-07-02 08:38:34 +00:00
}
2014-07-05 11:50:05 +00:00
2014-10-25 19:52:10 +00:00
buffers [ 0 ] = ( char * ) malloc ( BLOCKSIZE_I134 ) ;
buffers [ 1 ] = ( char * ) malloc ( BLOCKSIZE_I134 ) ;
2016-08-11 10:18:45 +00:00
if ( ( ! buffers [ 0 ] ) | | ( ! buffers [ 1 ] ) ) {
2016-11-17 21:02:06 +00:00
free ( buffers [ 0 ] ) ; free ( buffers [ 1 ] ) ;
2015-06-29 08:31:41 +00:00
DISPLAY ( " not enough memory for tests \n " ) ;
2014-10-25 19:52:10 +00:00
return 0 ;
}
2015-06-29 08:31:41 +00:00
2016-08-11 10:18:45 +00:00
for ( nbBuff = 2 ; nbBuff < MAX_NB_BUFF_I134 ; nbBuff + + ) {
2016-11-17 21:02:06 +00:00
DISPLAY ( " %3i \b \b \b \b " , nbBuff ) ; fflush ( stdout ) ;
2014-10-25 19:52:10 +00:00
buffers [ nbBuff ] = ( char * ) malloc ( BLOCKSIZE_I134 ) ;
2015-06-29 08:31:41 +00:00
if ( buffers [ nbBuff ] = = NULL ) goto _endOfTests ;
2014-10-25 19:52:10 +00:00
2016-11-14 04:50:58 +00:00
if ( ( ( uintptr_t ) buffers [ nbBuff ] > ( uintptr_t ) 0x80000000 ) & & ( ! highAddress ) ) {
2015-06-29 08:31:41 +00:00
DISPLAY ( " high address detected : " ) ;
2014-10-25 19:52:10 +00:00
fflush ( stdout ) ;
highAddress = 1 ;
}
2016-11-14 04:50:58 +00:00
{ size_t const sizeToGenerateOverflow = ( size_t ) ( - ( ( uintptr_t ) buffers [ nbBuff - 1 ] ) + 512 ) ;
2019-05-30 23:17:47 +00:00
int const nbOf255 = ( int ) ( ( sizeToGenerateOverflow / 255 ) + 1 ) ;
2016-08-11 10:18:45 +00:00
char * const input = buffers [ nbBuff - 1 ] ;
2014-10-25 19:52:10 +00:00
char * output = buffers [ nbBuff ] ;
int r ;
2016-08-11 10:18:45 +00:00
input [ 0 ] = ( char ) 0xF0 ; /* Literal length overflow */
2014-10-25 19:52:10 +00:00
input [ 1 ] = ( char ) 0xFF ;
input [ 2 ] = ( char ) 0xFF ;
input [ 3 ] = ( char ) 0xFF ;
2019-05-30 23:17:47 +00:00
{ int u ; for ( u = 4 ; u < = nbOf255 + 4 ; u + + ) input [ u ] = ( char ) 0xff ; }
2014-10-25 19:52:10 +00:00
r = LZ4_decompress_safe ( input , output , nbOf255 + 64 , BLOCKSIZE_I134 ) ;
2016-11-17 21:02:06 +00:00
if ( r > 0 ) { DISPLAY ( " LZ4_decompress_safe = %i \n " , r ) ; goto _overflowError ; }
2016-08-11 10:18:45 +00:00
input [ 0 ] = ( char ) 0x1F ; /* Match length overflow */
2014-10-25 19:52:10 +00:00
input [ 1 ] = ( char ) 0x01 ;
input [ 2 ] = ( char ) 0x01 ;
input [ 3 ] = ( char ) 0x00 ;
r = LZ4_decompress_safe ( input , output , nbOf255 + 64 , BLOCKSIZE_I134 ) ;
2016-11-17 21:02:06 +00:00
if ( r > 0 ) { DISPLAY ( " LZ4_decompress_safe = %i \n " , r ) ; goto _overflowError ; }
2014-10-25 19:52:10 +00:00
2016-08-11 10:18:45 +00:00
output = buffers [ nbBuff - 2 ] ; /* Reverse in/out pointer order */
input [ 0 ] = ( char ) 0xF0 ; /* Literal length overflow */
2014-10-25 19:52:10 +00:00
input [ 1 ] = ( char ) 0xFF ;
input [ 2 ] = ( char ) 0xFF ;
input [ 3 ] = ( char ) 0xFF ;
r = LZ4_decompress_safe ( input , output , nbOf255 + 64 , BLOCKSIZE_I134 ) ;
if ( r > 0 ) goto _overflowError ;
2016-08-11 10:18:45 +00:00
input [ 0 ] = ( char ) 0x1F ; /* Match length overflow */
2014-10-25 19:52:10 +00:00
input [ 1 ] = ( char ) 0x01 ;
input [ 2 ] = ( char ) 0x01 ;
input [ 3 ] = ( char ) 0x00 ;
r = LZ4_decompress_safe ( input , output , nbOf255 + 64 , BLOCKSIZE_I134 ) ;
if ( r > 0 ) goto _overflowError ;
}
2014-07-02 08:38:34 +00:00
}
2014-10-25 19:52:10 +00:00
nbBuff + + ;
2014-07-05 11:50:05 +00:00
_endOfTests :
2016-11-17 21:02:06 +00:00
{ int i ; for ( i = 0 ; i < nbBuff ; i + + ) free ( buffers [ i ] ) ; }
2015-06-29 08:31:41 +00:00
if ( ! highAddress ) DISPLAY ( " high address not possible \n " ) ;
else DISPLAY ( " all overflows correctly detected \n " ) ;
2014-10-25 19:52:10 +00:00
return 0 ;
2014-07-05 11:50:05 +00:00
_overflowError :
2015-06-29 08:31:41 +00:00
DISPLAY ( " Address space overflow error !! \n " ) ;
2014-10-25 19:52:10 +00:00
exit ( 1 ) ;
2014-07-02 08:38:34 +00:00
}
2018-02-05 23:18:00 +00:00
# ifdef __unix__ /* is expected to be triggered on linux+gcc */
static void * FUZ_createLowAddr ( size_t size )
{
void * const lowBuff = mmap ( ( void * ) ( 0x1000 ) , size ,
PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS ,
- 1 , 0 ) ;
DISPLAYLEVEL ( 2 , " generating low buffer at address %p \n " , lowBuff ) ;
return lowBuff ;
}
static void FUZ_freeLowAddr ( void * buffer , size_t size )
{
if ( munmap ( buffer , size ) ) {
perror ( " fuzzer: freeing low address buffer " ) ;
abort ( ) ;
}
}
# else
static void * FUZ_createLowAddr ( size_t size )
{
return malloc ( size ) ;
}
static void FUZ_freeLowAddr ( void * buffer , size_t size )
{
( void ) size ;
free ( buffer ) ;
}
# endif
2018-03-21 14:14:13 +00:00
2016-08-11 10:18:45 +00:00
/*! FUZ_findDiff() :
* find the first different byte between buff1 and buff2 .
* presumes buff1 ! = buff2 .
* presumes a difference exists before end of either buffer .
* Typically invoked after a checksum mismatch .
*/
2015-04-24 09:15:12 +00:00
static void FUZ_findDiff ( const void * buff1 , const void * buff2 )
{
2016-08-11 10:18:45 +00:00
const BYTE * const b1 = ( const BYTE * ) buff1 ;
const BYTE * const b2 = ( const BYTE * ) buff2 ;
2016-11-13 01:14:57 +00:00
size_t u = 0 ;
while ( b1 [ u ] = = b2 [ u ] ) u + + ;
2018-04-06 02:05:49 +00:00
DISPLAY ( " \n Wrong Byte at position %u \n " , ( unsigned ) u ) ;
2015-04-24 09:15:12 +00:00
}
2016-09-03 02:48:24 +00:00
static int FUZ_test ( U32 seed , U32 nbCycles , const U32 startCycle , const double compressibility , U32 duration_s )
2014-10-10 19:58:42 +00:00
{
unsigned long long bytes = 0 ;
unsigned long long cbytes = 0 ;
unsigned long long hcbytes = 0 ;
unsigned long long ccbytes = 0 ;
2016-11-13 01:14:57 +00:00
void * const CNBuffer = malloc ( COMPRESSIBLE_NOISE_LENGTH ) ;
2019-04-05 00:03:05 +00:00
size_t const compressedBufferSize = ( size_t ) LZ4_compressBound ( FUZ_MAX_BLOCK_SIZE ) ;
2016-11-13 01:14:57 +00:00
char * const compressedBuffer = ( char * ) malloc ( compressedBufferSize ) ;
char * const decodedBuffer = ( char * ) malloc ( FUZ_MAX_DICT_SIZE + FUZ_MAX_BLOCK_SIZE ) ;
2018-02-05 23:18:00 +00:00
size_t const labSize = 96 KB ;
void * const lowAddrBuffer = FUZ_createLowAddr ( labSize ) ;
2019-04-05 00:03:05 +00:00
void * const stateLZ4 = malloc ( ( size_t ) LZ4_sizeofState ( ) ) ;
void * const stateLZ4HC = malloc ( ( size_t ) LZ4_sizeofStateHC ( ) ) ;
2019-04-18 23:41:27 +00:00
LZ4_stream_t LZ4dictBody ;
LZ4_streamHC_t * LZ4dictHC = LZ4_createStreamHC ( ) ;
2014-10-19 15:06:33 +00:00
U32 coreRandState = seed ;
2016-09-03 02:48:24 +00:00
clock_t const clockStart = clock ( ) ;
clock_t const clockDuration = ( clock_t ) duration_s * CLOCKS_PER_SEC ;
2016-11-13 01:14:57 +00:00
int result = 0 ;
unsigned cycleNb ;
2019-04-18 19:05:50 +00:00
# define EXIT_MSG(...) { \
printf ( " Test %u : " , testNb ) ; printf ( __VA_ARGS__ ) ; \
printf ( " (seed %u, cycle %u) \n " , seed , cycleNb ) ; \
exit ( 1 ) ; \
}
# define FUZ_CHECKTEST(cond, ...) { if (cond) { EXIT_MSG(__VA_ARGS__) } }
2018-09-05 18:25:10 +00:00
2018-03-21 14:14:13 +00:00
# define FUZ_DISPLAYTEST(...) { \
testNb + + ; \
if ( g_displayLevel > = 4 ) { \
2018-09-05 18:25:10 +00:00
printf ( " \r %4u - %2u : " , cycleNb , testNb ) ; \
2018-03-21 14:14:13 +00:00
printf ( " " __VA_ARGS__ ) ; \
printf ( " " ) ; \
fflush ( stdout ) ; \
} }
2014-10-10 19:58:42 +00:00
2015-04-10 22:42:17 +00:00
/* init */
2019-04-18 23:41:27 +00:00
if ( ! CNBuffer | | ! compressedBuffer | | ! decodedBuffer | | ! LZ4dictHC ) {
2016-11-13 01:14:57 +00:00
DISPLAY ( " Not enough memory to start fuzzer tests " ) ;
2019-04-18 17:38:51 +00:00
exit ( 1 ) ;
2016-11-13 01:14:57 +00:00
}
2019-04-18 23:41:27 +00:00
if ( LZ4_initStream ( & LZ4dictBody , sizeof ( LZ4dictBody ) ) = = NULL ) abort ( ) ;
2016-11-13 01:14:57 +00:00
{ U32 randState = coreRandState ^ PRIME3 ;
FUZ_fillCompressibleNoiseBuffer ( CNBuffer , COMPRESSIBLE_NOISE_LENGTH , compressibility , & randState ) ;
}
2014-10-10 19:58:42 +00:00
2015-04-10 22:42:17 +00:00
/* move to startCycle */
2016-11-14 18:16:11 +00:00
for ( cycleNb = 0 ; cycleNb < startCycle ; cycleNb + + )
( void ) FUZ_rand ( & coreRandState ) ; /* sync coreRandState */
2014-10-10 19:58:42 +00:00
2015-04-10 22:42:17 +00:00
/* Main test loop */
2016-11-13 01:14:57 +00:00
for ( cycleNb = startCycle ;
( cycleNb < nbCycles ) | | ( FUZ_GetClockSpan ( clockStart ) < clockDuration ) ;
cycleNb + + ) {
2014-10-20 00:08:21 +00:00
U32 testNb = 0 ;
2016-11-13 01:14:57 +00:00
U32 randState = FUZ_rand ( & coreRandState ) ^ PRIME3 ;
int const blockSize = ( FUZ_rand ( & randState ) % ( FUZ_MAX_BLOCK_SIZE - 1 ) ) + 1 ;
2019-06-29 03:15:43 +00:00
int const blockStart = ( int ) ( FUZ_rand ( & randState ) % ( U32 ) ( COMPRESSIBLE_NOISE_LENGTH - blockSize - 1 ) ) + 1 ;
2016-11-13 01:14:57 +00:00
int const dictSizeRand = FUZ_rand ( & randState ) % FUZ_MAX_DICT_SIZE ;
2018-04-12 23:17:53 +00:00
int const dictSize = MIN ( dictSizeRand , blockStart - 1 ) ;
2016-12-28 16:47:10 +00:00
int const compressionLevel = FUZ_rand ( & randState ) % ( LZ4HC_CLEVEL_MAX + 1 ) ;
2018-02-05 23:18:00 +00:00
const char * block = ( ( char * ) CNBuffer ) + blockStart ;
2016-11-13 01:14:57 +00:00
const char * dict = block - dictSize ;
int compressedSize , HCcompressedSize ;
2014-10-10 19:58:42 +00:00
int blockContinueCompressedSize ;
2019-04-05 00:03:05 +00:00
U32 const crcOrig = XXH32 ( block , ( size_t ) blockSize , 0 ) ;
2016-11-13 01:14:57 +00:00
int ret ;
2014-10-10 19:58:42 +00:00
FUZ_displayUpdate ( cycleNb ) ;
/* Compression tests */
2018-02-05 23:18:00 +00:00
if ( ( ( FUZ_rand ( & randState ) & 63 ) = = 2 )
& & ( ( size_t ) blockSize < labSize ) ) {
memcpy ( lowAddrBuffer , block , blockSize ) ;
2018-04-10 03:38:00 +00:00
block = ( const char * ) lowAddrBuffer ;
2018-02-05 23:18:00 +00:00
}
2014-10-10 19:58:42 +00:00
2015-05-06 01:29:04 +00:00
/* Test compression destSize */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_destSize() " ) ;
2019-06-29 03:15:43 +00:00
{ int cSize , srcSize = blockSize ;
2019-05-29 18:19:10 +00:00
int const targetSize = srcSize * ( int ) ( ( FUZ_rand ( & randState ) & 127 ) + 1 ) > > 7 ;
2019-06-29 03:15:43 +00:00
char const endCheck = ( char ) ( FUZ_rand ( & randState ) & 255 ) ;
2015-05-06 01:29:04 +00:00
compressedBuffer [ targetSize ] = endCheck ;
2019-06-29 03:15:43 +00:00
cSize = LZ4_compress_destSize ( block , compressedBuffer , & srcSize , targetSize ) ;
FUZ_CHECKTEST ( cSize > targetSize , " LZ4_compress_destSize() result larger than dst buffer ! " ) ;
2015-05-06 01:29:04 +00:00
FUZ_CHECKTEST ( compressedBuffer [ targetSize ] ! = endCheck , " LZ4_compress_destSize() overwrite dst buffer ! " ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( srcSize > blockSize , " LZ4_compress_destSize() read more than src buffer ! " ) ;
DISPLAYLEVEL ( 5 , " destSize : %7i/%7i; content%7i/%7i " , cSize , targetSize , srcSize , blockSize ) ;
2016-08-11 10:18:45 +00:00
if ( targetSize > 0 ) {
2015-05-06 01:29:04 +00:00
/* check correctness */
2019-04-05 00:03:05 +00:00
U32 const crcBase = XXH32 ( block , ( size_t ) srcSize , 0 ) ;
2019-05-29 18:19:10 +00:00
char const canary = ( char ) ( FUZ_rand ( & randState ) & 255 ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( ( cSize = = 0 ) , " LZ4_compress_destSize() compression failed " ) ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2016-11-13 01:14:57 +00:00
decodedBuffer [ srcSize ] = canary ;
2019-06-29 03:15:43 +00:00
{ int const dSize = LZ4_decompress_safe ( compressedBuffer , decodedBuffer , cSize , srcSize ) ;
FUZ_CHECKTEST ( dSize < 0 , " LZ4_decompress_safe() failed on data compressed by LZ4_compress_destSize " ) ;
FUZ_CHECKTEST ( dSize ! = srcSize , " LZ4_decompress_safe() failed : did not fully decompressed data " ) ;
}
2016-11-13 01:14:57 +00:00
FUZ_CHECKTEST ( decodedBuffer [ srcSize ] ! = canary , " LZ4_decompress_safe() overwrite dst buffer ! " ) ;
2019-06-29 03:15:43 +00:00
{ U32 const crcDec = XXH32 ( decodedBuffer , ( size_t ) srcSize , 0 ) ;
FUZ_CHECKTEST ( crcDec ! = crcBase , " LZ4_decompress_safe() corrupted decoded data " ) ;
} }
DISPLAYLEVEL ( 5 , " OK \n " ) ;
}
2015-05-06 01:29:04 +00:00
2017-03-08 08:13:28 +00:00
/* Test compression HC destSize */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC_destSize() " ) ;
2019-06-29 03:15:43 +00:00
{ int cSize , srcSize = blockSize ;
2019-05-29 18:19:10 +00:00
int const targetSize = srcSize * ( int ) ( ( FUZ_rand ( & randState ) & 127 ) + 1 ) > > 7 ;
char const endCheck = ( char ) ( FUZ_rand ( & randState ) & 255 ) ;
2019-06-29 03:15:43 +00:00
void * const ctx = LZ4_createHC ( block ) ;
2017-03-08 08:13:28 +00:00
FUZ_CHECKTEST ( ctx = = NULL , " LZ4_createHC() allocation failed " ) ;
compressedBuffer [ targetSize ] = endCheck ;
2019-06-29 03:15:43 +00:00
cSize = LZ4_compress_HC_destSize ( ctx , block , compressedBuffer , & srcSize , targetSize , compressionLevel ) ;
2017-12-22 11:47:59 +00:00
DISPLAYLEVEL ( 5 , " LZ4_compress_HC_destSize(%i): destSize : %7i/%7i; content%7i/%7i " ,
2019-06-29 03:15:43 +00:00
compressionLevel , cSize , targetSize , srcSize , blockSize ) ;
2017-03-08 08:13:28 +00:00
LZ4_freeHC ( ctx ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( cSize > targetSize , " LZ4_compress_HC_destSize() result larger than dst buffer ! " ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( compressedBuffer [ targetSize ] ! = endCheck , " LZ4_compress_HC_destSize() overwrite dst buffer ! " ) ;
FUZ_CHECKTEST ( srcSize > blockSize , " LZ4_compress_HC_destSize() fed more than src buffer ! " ) ;
2017-03-08 08:13:28 +00:00
if ( targetSize > 0 ) {
/* check correctness */
2019-04-05 00:03:05 +00:00
U32 const crcBase = XXH32 ( block , ( size_t ) srcSize , 0 ) ;
2019-05-29 18:19:10 +00:00
char const canary = ( char ) ( FUZ_rand ( & randState ) & 255 ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( ( cSize = = 0 ) , " LZ4_compress_HC_destSize() compression failed " ) ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2017-03-08 08:13:28 +00:00
decodedBuffer [ srcSize ] = canary ;
2019-06-29 03:15:43 +00:00
{ int const dSize = LZ4_decompress_safe ( compressedBuffer , decodedBuffer , cSize , srcSize ) ;
FUZ_CHECKTEST ( dSize < 0 , " LZ4_decompress_safe() failed on data compressed by LZ4_compressHC_destSize " ) ;
FUZ_CHECKTEST ( dSize ! = srcSize , " LZ4_decompress_safe() failed : did not fully decompressed data " ) ;
}
2017-03-08 08:13:28 +00:00
FUZ_CHECKTEST ( decodedBuffer [ srcSize ] ! = canary , " LZ4_decompress_safe() overwrite dst buffer ! " ) ;
2019-05-29 18:19:10 +00:00
{ U32 const crcDec = XXH32 ( decodedBuffer , ( size_t ) srcSize , 0 ) ;
2017-11-03 18:28:28 +00:00
FUZ_CHECKTEST ( crcDec ! = crcBase , " LZ4_decompress_safe() corrupted decoded data " ) ;
2019-06-29 03:15:43 +00:00
} }
DISPLAYLEVEL ( 5 , " OK \n " ) ;
}
2017-03-08 08:13:28 +00:00
2015-04-10 22:42:17 +00:00
/* Test compression HC */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC() " ) ;
2019-04-18 23:41:27 +00:00
HCcompressedSize = LZ4_compress_HC ( block , compressedBuffer , blockSize , ( int ) compressedBufferSize , compressionLevel ) ;
FUZ_CHECKTEST ( HCcompressedSize = = 0 , " LZ4_compress_HC() failed " ) ;
2014-10-10 19:58:42 +00:00
2015-04-24 09:15:12 +00:00
/* Test compression HC using external state */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC_extStateHC() " ) ;
2019-04-18 23:41:27 +00:00
{ int const r = LZ4_compress_HC_extStateHC ( stateLZ4HC , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , compressionLevel ) ;
FUZ_CHECKTEST ( r = = 0 , " LZ4_compress_HC_extStateHC() failed " )
}
2018-04-20 19:16:41 +00:00
/* Test compression HC using fast reset external state */
FUZ_DISPLAYTEST ( " test LZ4_compress_HC_extStateHC_fastReset() " ) ;
2019-04-18 23:41:27 +00:00
{ int const r = LZ4_compress_HC_extStateHC_fastReset ( stateLZ4HC , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , compressionLevel ) ;
FUZ_CHECKTEST ( r = = 0 , " LZ4_compress_HC_extStateHC_fastReset() failed " ) ;
}
2014-10-10 19:58:42 +00:00
2015-04-24 09:15:12 +00:00
/* Test compression using external state */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_fast_extState() " ) ;
2019-04-18 23:41:27 +00:00
{ int const r = LZ4_compress_fast_extState ( stateLZ4 , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 8 ) ;
FUZ_CHECKTEST ( r = = 0 , " LZ4_compress_fast_extState() failed " ) ; }
2014-10-10 19:58:42 +00:00
2018-04-12 22:23:01 +00:00
/* Test compression using fast reset external state*/
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-04-18 23:41:27 +00:00
{ int const r = LZ4_compress_fast_extState_fastReset ( stateLZ4 , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 8 ) ;
FUZ_CHECKTEST ( r = = 0 , " LZ4_compress_fast_extState_fastReset() failed " ) ; }
2018-04-12 22:23:01 +00:00
2015-04-24 09:15:12 +00:00
/* Test compression */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_default() " ) ;
2019-04-18 23:41:27 +00:00
compressedSize = LZ4_compress_default ( block , compressedBuffer , blockSize , ( int ) compressedBufferSize ) ;
FUZ_CHECKTEST ( compressedSize < = 0 , " LZ4_compress_default() failed " ) ;
2014-10-10 19:58:42 +00:00
/* Decompression tests */
2019-04-17 20:31:24 +00:00
/* Test decompress_fast() with input buffer size exactly correct => must not read out of bound */
2019-04-17 22:44:14 +00:00
{ char * const cBuffer_exact = ( char * ) malloc ( ( size_t ) compressedSize ) ;
2019-04-17 20:31:24 +00:00
assert ( cBuffer_exact ! = NULL ) ;
2019-04-18 23:41:27 +00:00
assert ( compressedSize < = ( int ) compressedBufferSize ) ;
2019-04-17 20:31:24 +00:00
memcpy ( cBuffer_exact , compressedBuffer , compressedSize ) ;
/* Test decoding with output size exactly correct => must work */
FUZ_DISPLAYTEST ( " LZ4_decompress_fast() with exact output buffer " ) ;
2019-04-19 01:50:51 +00:00
{ int const r = LZ4_decompress_fast ( cBuffer_exact , decodedBuffer , blockSize ) ;
FUZ_CHECKTEST ( r < 0 , " LZ4_decompress_fast failed despite correct space " ) ;
FUZ_CHECKTEST ( r ! = compressedSize , " LZ4_decompress_fast failed : did not fully read compressed data " ) ;
}
2019-04-17 20:31:24 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_fast corrupted decoded data " ) ;
}
/* Test decoding with one byte missing => must fail */
FUZ_DISPLAYTEST ( " LZ4_decompress_fast() with output buffer 1-byte too short " ) ;
decodedBuffer [ blockSize - 1 ] = 0 ;
2019-04-19 01:50:51 +00:00
{ int const r = LZ4_decompress_fast ( cBuffer_exact , decodedBuffer , blockSize - 1 ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_fast should have failed, due to Output Size being too small " ) ;
}
2019-04-18 17:38:51 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] ! = 0 , " LZ4_decompress_fast overrun specified output buffer " ) ;
2019-04-17 20:31:24 +00:00
/* Test decoding with one byte too much => must fail */
FUZ_DISPLAYTEST ( ) ;
2019-04-19 01:50:51 +00:00
{ int const r = LZ4_decompress_fast ( cBuffer_exact , decodedBuffer , blockSize + 1 ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_fast should have failed, due to Output Size being too large " ) ;
}
2018-04-23 20:14:19 +00:00
2019-04-19 01:50:51 +00:00
/* Test decoding with output size exactly what's necessary => must work */
FUZ_DISPLAYTEST ( ) ;
decodedBuffer [ blockSize ] = 0 ;
{ int const r = LZ4_decompress_safe ( cBuffer_exact , decodedBuffer , compressedSize , blockSize ) ;
FUZ_CHECKTEST ( r < 0 , " LZ4_decompress_safe failed despite sufficient space " ) ;
FUZ_CHECKTEST ( r ! = blockSize , " LZ4_decompress_safe did not regenerate original data " ) ;
}
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe overrun specified output buffer size " ) ;
2019-05-29 18:19:10 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2019-04-19 01:50:51 +00:00
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_safe corrupted decoded data " ) ;
}
2018-04-23 20:14:19 +00:00
2019-04-19 01:50:51 +00:00
/* Test decoding with more than enough output size => must work */
FUZ_DISPLAYTEST ( ) ;
decodedBuffer [ blockSize ] = 0 ;
decodedBuffer [ blockSize + 1 ] = 0 ;
{ int const r = LZ4_decompress_safe ( cBuffer_exact , decodedBuffer , compressedSize , blockSize + 1 ) ;
FUZ_CHECKTEST ( r < 0 , " LZ4_decompress_safe failed despite amply sufficient space " ) ;
FUZ_CHECKTEST ( r ! = blockSize , " LZ4_decompress_safe did not regenerate original data " ) ;
}
FUZ_CHECKTEST ( decodedBuffer [ blockSize + 1 ] , " LZ4_decompress_safe overrun specified output buffer size " ) ;
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_safe corrupted decoded data " ) ;
}
2018-04-23 20:14:19 +00:00
2019-04-19 01:50:51 +00:00
/* Test decoding with output size being one byte too short => must fail */
FUZ_DISPLAYTEST ( ) ;
decodedBuffer [ blockSize - 1 ] = 0 ;
{ int const r = LZ4_decompress_safe ( cBuffer_exact , decodedBuffer , compressedSize , blockSize - 1 ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_safe should have failed, due to Output Size being one byte too short " ) ;
}
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] , " LZ4_decompress_safe overrun specified output buffer size " ) ;
2018-04-23 20:14:19 +00:00
2019-04-19 01:50:51 +00:00
/* Test decoding with output size being 10 bytes too short => must fail */
FUZ_DISPLAYTEST ( ) ;
if ( blockSize > 10 ) {
decodedBuffer [ blockSize - 10 ] = 0 ;
{ int const r = LZ4_decompress_safe ( cBuffer_exact , decodedBuffer , compressedSize , blockSize - 10 ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_safe should have failed, due to Output Size being 10 bytes too short " ) ;
}
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 10 ] , " LZ4_decompress_safe overrun specified output buffer size " ) ;
}
2014-10-10 19:58:42 +00:00
2019-06-29 03:23:12 +00:00
/* noisy src decompression test */
2014-10-10 19:58:42 +00:00
2019-06-29 03:15:43 +00:00
/* insert noise into src */
{ U32 const maxNbBits = FUZ_highbit32 ( ( U32 ) compressedSize ) ;
size_t pos = 0 ;
for ( ; ; ) {
/* keep some original src */
{ U32 const nbBits = FUZ_rand ( & randState ) % maxNbBits ;
size_t const mask = ( 1 < < nbBits ) - 1 ;
size_t const skipLength = FUZ_rand ( & randState ) & mask ;
pos + = skipLength ;
}
if ( pos > = ( size_t ) compressedSize ) break ;
/* add noise */
{ U32 const nbBitsCodes = FUZ_rand ( & randState ) % maxNbBits ;
U32 const nbBits = nbBitsCodes ? nbBitsCodes - 1 : 0 ;
size_t const mask = ( 1 < < nbBits ) - 1 ;
size_t const rNoiseLength = ( FUZ_rand ( & randState ) & mask ) + 1 ;
size_t const noiseLength = MIN ( rNoiseLength , ( size_t ) compressedSize - pos ) ;
size_t const noiseStart = FUZ_rand ( & randState ) % ( COMPRESSIBLE_NOISE_LENGTH - noiseLength ) ;
2019-06-29 03:23:12 +00:00
memcpy ( cBuffer_exact + pos , ( const char * ) CNBuffer + noiseStart , noiseLength ) ;
2019-06-29 03:15:43 +00:00
pos + = noiseLength ;
} } }
/* decompress noisy source */
2019-06-29 03:23:12 +00:00
FUZ_DISPLAYTEST ( " decompress noisy source " ) ;
2019-06-29 03:15:43 +00:00
{ U32 const endMark = 0xA9B1C3D6 ;
memcpy ( decodedBuffer + blockSize , & endMark , sizeof ( endMark ) ) ;
2019-06-29 03:23:12 +00:00
{ int const decompressResult = LZ4_decompress_safe ( cBuffer_exact , decodedBuffer , compressedSize , blockSize ) ;
2019-06-29 03:15:43 +00:00
/* result *may* be an unlikely success, but even then, it must strictly respect dst buffer boundaries */
FUZ_CHECKTEST ( decompressResult > blockSize , " LZ4_decompress_safe on noisy src : result is too large : %u > %u (dst buffer) " , ( unsigned ) decompressResult , ( unsigned ) blockSize ) ;
}
{ U32 endCheck ; memcpy ( & endCheck , decodedBuffer + blockSize , sizeof ( endCheck ) ) ;
FUZ_CHECKTEST ( endMark ! = endCheck , " LZ4_decompress_safe on noisy src : dst buffer overflow " ) ;
2019-06-29 03:23:12 +00:00
} } /* noisy src decompression test */
free ( cBuffer_exact ) ;
}
/* Test decoding with input size being one byte too short => must fail */
FUZ_DISPLAYTEST ( ) ;
{ int const r = LZ4_decompress_safe ( compressedBuffer , decodedBuffer , compressedSize - 1 , blockSize ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_safe should have failed, due to input size being one byte too short (blockSize=%i, result=%i, compressedSize=%i) " , blockSize , r , compressedSize ) ;
}
/* Test decoding with input size being one byte too large => must fail */
FUZ_DISPLAYTEST ( ) ;
decodedBuffer [ blockSize ] = 0 ;
{ int const r = LZ4_decompress_safe ( compressedBuffer , decodedBuffer , compressedSize + 1 , blockSize ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_safe should have failed, due to input size being too large " ) ;
}
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe overrun specified output buffer size " ) ;
/* Test partial decoding => must work */
FUZ_DISPLAYTEST ( " test LZ4_decompress_safe_partial " ) ;
2020-08-27 07:17:57 +00:00
{ size_t const missingOutBytes = FUZ_rand ( & randState ) % ( unsigned ) blockSize ;
int const targetSize = ( int ) ( ( size_t ) blockSize - missingOutBytes ) ;
2020-08-12 21:39:01 +00:00
size_t const extraneousInBytes = FUZ_rand ( & randState ) % 2 ;
int const inCSize = ( int ) ( ( size_t ) compressedSize + extraneousInBytes ) ;
2019-06-29 03:23:12 +00:00
char const sentinel = decodedBuffer [ targetSize ] = block [ targetSize ] ^ 0x5A ;
2020-08-12 21:39:01 +00:00
int const decResult = LZ4_decompress_safe_partial ( compressedBuffer , decodedBuffer , inCSize , targetSize , blockSize ) ;
2019-06-29 03:23:12 +00:00
FUZ_CHECKTEST ( decResult < 0 , " LZ4_decompress_safe_partial failed despite valid input data (error:%i) " , decResult ) ;
FUZ_CHECKTEST ( decResult ! = targetSize , " LZ4_decompress_safe_partial did not regenerated required amount of data (%i < %i <= %i) " , decResult , targetSize , blockSize ) ;
FUZ_CHECKTEST ( decodedBuffer [ targetSize ] ! = sentinel , " LZ4_decompress_safe_partial overwrite beyond requested size (though %i <= %i <= %i) " , decResult , targetSize , blockSize ) ;
2020-08-12 21:39:01 +00:00
FUZ_CHECKTEST ( memcmp ( block , decodedBuffer , ( size_t ) targetSize ) , " LZ4_decompress_safe_partial: corruption detected in regenerated data " ) ;
2019-06-29 03:23:12 +00:00
}
2019-06-29 03:15:43 +00:00
2014-10-10 19:58:42 +00:00
/* Test Compression with limited output size */
2014-12-10 08:05:44 +00:00
/* Test compression with output size being exactly what's necessary (should work) */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_default() with output buffer just the right size " ) ;
2016-11-12 16:48:42 +00:00
ret = LZ4_compress_default ( block , compressedBuffer , blockSize , compressedSize ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret = = 0 , " LZ4_compress_default() failed despite sufficient space " ) ;
2014-10-10 19:58:42 +00:00
2014-12-10 08:05:44 +00:00
/* Test compression with output size being exactly what's necessary and external state (should work) */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_fast_extState() with output buffer just the right size " ) ;
2016-11-12 16:48:42 +00:00
ret = LZ4_compress_fast_extState ( stateLZ4 , block , compressedBuffer , blockSize , compressedSize , 1 ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret = = 0 , " LZ4_compress_fast_extState() failed despite sufficient space " ) ;
2014-10-10 19:58:42 +00:00
2014-12-10 08:05:44 +00:00
/* Test HC compression with output size being exactly what's necessary (should work) */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC() with output buffer just the right size " ) ;
2016-12-28 16:47:10 +00:00
ret = LZ4_compress_HC ( block , compressedBuffer , blockSize , HCcompressedSize , compressionLevel ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret = = 0 , " LZ4_compress_HC() failed despite sufficient space " ) ;
2014-10-10 19:58:42 +00:00
2014-12-10 08:05:44 +00:00
/* Test HC compression with output size being exactly what's necessary (should work) */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC_extStateHC() with output buffer just the right size " ) ;
2016-12-28 16:47:10 +00:00
ret = LZ4_compress_HC_extStateHC ( stateLZ4HC , block , compressedBuffer , blockSize , HCcompressedSize , compressionLevel ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret = = 0 , " LZ4_compress_HC_extStateHC() failed despite sufficient space " ) ;
2014-10-10 19:58:42 +00:00
2014-12-10 16:58:15 +00:00
/* Test compression with missing bytes into output buffer => must fail */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_default() with output buffer a bit too short " ) ;
2016-08-11 10:18:45 +00:00
{ int missingBytes = ( FUZ_rand ( & randState ) % 0x3F ) + 1 ;
2014-12-10 08:05:44 +00:00
if ( missingBytes > = compressedSize ) missingBytes = compressedSize - 1 ;
2014-12-10 16:58:15 +00:00
missingBytes + = ! missingBytes ; /* avoid special case missingBytes==0 */
2014-12-10 08:05:44 +00:00
compressedBuffer [ compressedSize - missingBytes ] = 0 ;
2019-06-29 03:15:43 +00:00
{ int const cSize = LZ4_compress_default ( block , compressedBuffer , blockSize , compressedSize - missingBytes ) ;
FUZ_CHECKTEST ( cSize , " LZ4_compress_default should have failed (output buffer too small by %i byte) " , missingBytes ) ;
}
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( compressedBuffer [ compressedSize - missingBytes ] , " LZ4_compress_default overran output buffer ! (%i missingBytes) " , missingBytes )
2014-12-10 08:05:44 +00:00
}
2014-12-10 16:58:15 +00:00
/* Test HC compression with missing bytes into output buffer => must fail */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_HC() with output buffer a bit too short " ) ;
2016-08-11 10:18:45 +00:00
{ int missingBytes = ( FUZ_rand ( & randState ) % 0x3F ) + 1 ;
2014-12-10 16:58:15 +00:00
if ( missingBytes > = HCcompressedSize ) missingBytes = HCcompressedSize - 1 ;
missingBytes + = ! missingBytes ; /* avoid special case missingBytes==0 */
compressedBuffer [ HCcompressedSize - missingBytes ] = 0 ;
2019-06-29 03:15:43 +00:00
{ int const hcSize = LZ4_compress_HC ( block , compressedBuffer , blockSize , HCcompressedSize - missingBytes , compressionLevel ) ;
FUZ_CHECKTEST ( hcSize , " LZ4_compress_HC should have failed (output buffer too small by %i byte) " , missingBytes ) ;
}
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( compressedBuffer [ HCcompressedSize - missingBytes ] , " LZ4_compress_HC overran output buffer ! (%i missingBytes) " , missingBytes )
2014-12-10 16:58:15 +00:00
}
2014-10-10 19:58:42 +00:00
2016-08-11 10:18:45 +00:00
/*-******************/
2014-12-10 08:05:44 +00:00
/* Dictionary tests */
2016-08-11 10:18:45 +00:00
/*-******************/
2014-12-10 08:05:44 +00:00
/* Compress using dictionary */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_fast_continue() with dictionary of size %i " , dictSize ) ;
2016-08-11 10:18:45 +00:00
{ LZ4_stream_t LZ4_stream ;
2019-04-05 19:54:13 +00:00
LZ4_initStream ( & LZ4_stream , sizeof ( LZ4_stream ) ) ;
2016-11-14 15:10:31 +00:00
LZ4_compress_fast_continue ( & LZ4_stream , dict , compressedBuffer , dictSize , ( int ) compressedBufferSize , 1 ) ; /* Just to fill hash tables */
blockContinueCompressedSize = LZ4_compress_fast_continue ( & LZ4_stream , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 1 ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_fast_continue failed " ) ;
2015-04-11 17:59:22 +00:00
}
2014-10-10 19:58:42 +00:00
2014-12-10 08:05:44 +00:00
/* Decompress with dictionary as prefix */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_decompress_fast_usingDict() with dictionary as prefix " ) ;
2014-10-10 19:58:42 +00:00
memcpy ( decodedBuffer , dict , dictSize ) ;
2015-04-11 17:59:22 +00:00
ret = LZ4_decompress_fast_usingDict ( compressedBuffer , decodedBuffer + dictSize , blockSize , decodedBuffer , dictSize ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_decompress_fast_usingDict did not read all compressed block input " ) ;
2019-04-05 00:03:05 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer + dictSize , ( size_t ) blockSize , 0 ) ;
2019-04-18 19:05:50 +00:00
if ( crcCheck ! = crcOrig ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_fast_usingDict corrupted decoded data (dict %i) " , dictSize ) ;
2019-06-29 03:15:43 +00:00
} }
2014-10-10 19:58:42 +00:00
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_decompress_safe_usingDict() " ) ;
2015-04-11 17:59:22 +00:00
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer + dictSize , blockContinueCompressedSize , blockSize , decodedBuffer , dictSize ) ;
2015-04-24 09:15:12 +00:00
FUZ_CHECKTEST ( ret ! = blockSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
2019-04-05 00:03:05 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer + dictSize , ( size_t ) blockSize , 0 ) ;
2018-04-06 02:05:49 +00:00
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
}
2014-10-10 19:58:42 +00:00
2015-04-12 07:21:35 +00:00
/* Compress using External dictionary */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_fast_continue(), with non-contiguous dictionary " ) ;
2019-04-13 00:40:23 +00:00
dict - = ( size_t ) ( FUZ_rand ( & randState ) & 0xF ) + 1 ; /* create space, so now dictionary is an ExtDict */
2014-10-10 19:58:42 +00:00
if ( dict < ( char * ) CNBuffer ) dict = ( char * ) CNBuffer ;
2019-04-18 23:41:27 +00:00
LZ4_loadDict ( & LZ4dictBody , dict , dictSize ) ;
blockContinueCompressedSize = LZ4_compress_fast_continue ( & LZ4dictBody , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 1 ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_fast_continue failed " ) ;
2014-10-10 19:58:42 +00:00
2019-06-29 03:23:12 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_fast_continue() with dictionary and output buffer too short by one byte " ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDict ( & LZ4dictBody , dict , dictSize ) ;
ret = LZ4_compress_fast_continue ( & LZ4dictBody , block , compressedBuffer , blockSize , blockContinueCompressedSize - 1 , 1 ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret > 0 , " LZ4_compress_fast_continue using ExtDict should fail : one missing byte for output buffer : %i written, %i buffer " , ret , blockContinueCompressedSize ) ;
2014-10-10 19:58:42 +00:00
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( " test LZ4_compress_fast_continue() with dictionary loaded with LZ4_loadDict() " ) ;
2018-12-02 13:12:24 +00:00
DISPLAYLEVEL ( 5 , " compress %i bytes from buffer(%p) into dst(%p) using dict(%p) of size %i \n " ,
2018-12-02 13:30:25 +00:00
blockSize , ( const void * ) block , ( void * ) decodedBuffer , ( const void * ) dict , dictSize ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDict ( & LZ4dictBody , dict , dictSize ) ;
ret = LZ4_compress_fast_continue ( & LZ4dictBody , block , compressedBuffer , blockSize , blockContinueCompressedSize , 1 ) ;
2014-10-10 19:58:42 +00:00
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_limitedOutput_compressed size is different (%i != %i) " , ret , blockContinueCompressedSize ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_fast_continue should work : enough size available within output buffer " ) ;
2014-10-10 19:58:42 +00:00
2015-04-24 09:15:12 +00:00
/* Decompress with dictionary as external */
2018-04-12 14:25:40 +00:00
FUZ_DISPLAYTEST ( " test LZ4_decompress_fast_usingDict() with dictionary as extDict " ) ;
2018-12-02 13:30:25 +00:00
DISPLAYLEVEL ( 5 , " decoding %i bytes from buffer(%p) using dict(%p) of size %i \n " ,
blockSize , ( void * ) decodedBuffer , ( const void * ) dict , dictSize ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_fast_usingDict ( compressedBuffer , decodedBuffer , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_decompress_fast_usingDict did not read all compressed block input " ) ;
2016-11-13 01:14:57 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_fast_usingDict overrun specified output buffer size " ) ;
2019-04-18 19:05:50 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
if ( crcCheck ! = crcOrig ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_fast_usingDict corrupted decoded data (dict %i) " , dictSize ) ;
2019-06-29 03:15:43 +00:00
} }
2014-10-10 19:58:42 +00:00
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
2016-11-13 01:14:57 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
2019-05-30 23:17:47 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2018-04-06 02:05:49 +00:00
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
}
2014-10-10 19:58:42 +00:00
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize - 1 ] = 0 ;
ret = LZ4_decompress_fast_usingDict ( compressedBuffer , decodedBuffer , blockSize - 1 , dict , dictSize ) ;
2015-04-24 09:15:12 +00:00
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_fast_usingDict should have failed : wrong original size (-1 byte) " ) ;
2014-10-10 19:58:42 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] , " LZ4_decompress_fast_usingDict overrun specified output buffer size " ) ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize - 1 ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize - 1 , dict , dictSize ) ;
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_safe_usingDict should have failed : not enough output size (-1 byte) " ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-06-29 03:15:43 +00:00
{ int const missingBytes = ( FUZ_rand ( & randState ) & 0xF ) + 2 ;
if ( blockSize > missingBytes ) {
2014-10-20 00:08:21 +00:00
decodedBuffer [ blockSize - missingBytes ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize - missingBytes , dict , dictSize ) ;
2019-06-29 03:55:47 +00:00
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%i byte) " , missingBytes ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize - missingBytes ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size (-%i byte) (blockSize=%i) " , missingBytes , blockSize ) ;
2018-04-12 22:23:01 +00:00
} }
/* Compress using external dictionary stream */
2019-06-29 03:15:43 +00:00
{ LZ4_stream_t LZ4_stream ;
2018-04-12 23:17:53 +00:00
int expectedSize ;
U32 expectedCrc ;
2018-04-17 00:15:02 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_fast_continue() after LZ4_loadDict() " ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDict ( & LZ4dictBody , dict , dictSize ) ;
expectedSize = LZ4_compress_fast_continue ( & LZ4dictBody , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 1 ) ;
2018-04-12 23:17:53 +00:00
FUZ_CHECKTEST ( expectedSize < = 0 , " LZ4_compress_fast_continue reference compression for extDictCtx should have succeeded " ) ;
2019-06-29 03:15:43 +00:00
expectedCrc = XXH32 ( compressedBuffer , ( size_t ) expectedSize , 0 ) ;
2018-04-12 22:23:01 +00:00
2018-04-17 00:15:02 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_fast_continue() after LZ4_attach_dictionary() " ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDict ( & LZ4dictBody , dict , dictSize ) ;
2019-04-05 19:54:13 +00:00
LZ4_initStream ( & LZ4_stream , sizeof ( LZ4_stream ) ) ;
2019-04-18 23:41:27 +00:00
LZ4_attach_dictionary ( & LZ4_stream , & LZ4dictBody ) ;
2018-04-12 22:23:01 +00:00
blockContinueCompressedSize = LZ4_compress_fast_continue ( & LZ4_stream , block , compressedBuffer , blockSize , ( int ) compressedBufferSize , 1 ) ;
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_fast_continue using extDictCtx failed " ) ;
2018-04-12 23:17:53 +00:00
/* In the future, it might be desirable to let extDictCtx mode's
* output diverge from the output generated by regular extDict mode .
* Until that time , this comparison serves as a good regression
* test .
*/
FUZ_CHECKTEST ( blockContinueCompressedSize ! = expectedSize , " LZ4_compress_fast_continue using extDictCtx produced different-sized output (%d expected vs %d actual) " , expectedSize , blockContinueCompressedSize ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( XXH32 ( compressedBuffer , ( size_t ) blockContinueCompressedSize , 0 ) ! = expectedCrc , " LZ4_compress_fast_continue using extDictCtx produced different output " ) ;
2018-04-12 23:17:53 +00:00
2018-04-17 00:15:02 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_fast_continue() after LZ4_attach_dictionary(), but output buffer is 1 byte too short " ) ;
2018-09-18 18:29:31 +00:00
LZ4_resetStream_fast ( & LZ4_stream ) ;
2019-04-18 23:41:27 +00:00
LZ4_attach_dictionary ( & LZ4_stream , & LZ4dictBody ) ;
2018-04-12 22:23:01 +00:00
ret = LZ4_compress_fast_continue ( & LZ4_stream , block , compressedBuffer , blockSize , blockContinueCompressedSize - 1 , 1 ) ;
FUZ_CHECKTEST ( ret > 0 , " LZ4_compress_fast_continue using extDictCtx should fail : one missing byte for output buffer : %i written, %i buffer " , ret , blockContinueCompressedSize ) ;
2019-04-15 18:12:54 +00:00
/* note : context is no longer dirty after a failed compressed block */
2018-04-12 22:23:01 +00:00
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2018-09-18 18:29:31 +00:00
LZ4_resetStream_fast ( & LZ4_stream ) ;
2019-04-18 23:41:27 +00:00
LZ4_attach_dictionary ( & LZ4_stream , & LZ4dictBody ) ;
2018-04-12 22:23:01 +00:00
ret = LZ4_compress_fast_continue ( & LZ4_stream , block , compressedBuffer , blockSize , blockContinueCompressedSize , 1 ) ;
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_limitedOutput_compressed size is different (%i != %i) " , ret , blockContinueCompressedSize ) ;
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_fast_continue using extDictCtx should work : enough size available within output buffer " ) ;
2018-04-12 23:17:53 +00:00
FUZ_CHECKTEST ( ret ! = expectedSize , " LZ4_compress_fast_continue using extDictCtx produced different-sized output " ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( XXH32 ( compressedBuffer , ( size_t ) ret , 0 ) ! = expectedCrc , " LZ4_compress_fast_continue using extDictCtx produced different output " ) ;
2018-04-12 22:23:01 +00:00
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2018-04-12 22:23:01 +00:00
LZ4_resetStream_fast ( & LZ4_stream ) ;
2019-04-18 23:41:27 +00:00
LZ4_attach_dictionary ( & LZ4_stream , & LZ4dictBody ) ;
2018-04-12 22:23:01 +00:00
ret = LZ4_compress_fast_continue ( & LZ4_stream , block , compressedBuffer , blockSize , blockContinueCompressedSize , 1 ) ;
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_limitedOutput_compressed size is different (%i != %i) " , ret , blockContinueCompressedSize ) ;
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_fast_continue using extDictCtx with re-used context should work : enough size available within output buffer " ) ;
2018-04-12 23:17:53 +00:00
FUZ_CHECKTEST ( ret ! = expectedSize , " LZ4_compress_fast_continue using extDictCtx produced different-sized output " ) ;
2019-06-29 03:15:43 +00:00
FUZ_CHECKTEST ( XXH32 ( compressedBuffer , ( size_t ) ret , 0 ) ! = expectedCrc , " LZ4_compress_fast_continue using extDictCtx produced different output " ) ;
2018-04-12 22:23:01 +00:00
}
/* Decompress with dictionary as external */
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2018-04-12 22:23:01 +00:00
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_fast_usingDict ( compressedBuffer , decodedBuffer , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_decompress_fast_usingDict did not read all compressed block input " ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_fast_usingDict overrun specified output buffer size " ) ;
2019-05-30 23:17:47 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2019-04-18 19:05:50 +00:00
if ( crcCheck ! = crcOrig ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_fast_usingDict corrupted decoded data (dict %i) " , dictSize ) ;
2019-05-30 23:17:47 +00:00
} }
2014-10-10 19:58:42 +00:00
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
2016-11-13 01:14:57 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
2019-04-09 20:55:42 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2018-04-16 23:14:28 +00:00
FUZ_CHECKTEST ( crcCheck ! = crcOrig , " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
}
2014-10-10 19:58:42 +00:00
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize - 1 ] = 0 ;
ret = LZ4_decompress_fast_usingDict ( compressedBuffer , decodedBuffer , blockSize - 1 , dict , dictSize ) ;
2015-04-24 09:15:12 +00:00
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_fast_usingDict should have failed : wrong original size (-1 byte) " ) ;
2014-10-10 19:58:42 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] , " LZ4_decompress_fast_usingDict overrun specified output buffer size " ) ;
2018-04-16 23:14:28 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-10 19:58:42 +00:00
decodedBuffer [ blockSize - 1 ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize - 1 , dict , dictSize ) ;
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_safe_usingDict should have failed : not enough output size (-1 byte) " ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize - 1 ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
2018-09-05 18:25:10 +00:00
FUZ_DISPLAYTEST ( " LZ4_decompress_safe_usingDict with a too small output buffer " ) ;
2020-08-12 21:39:01 +00:00
{ int const missingBytes = ( FUZ_rand ( & randState ) & 0xF ) + 2 ;
if ( blockSize > missingBytes ) {
decodedBuffer [ blockSize - missingBytes ] = 0 ;
2014-10-20 00:08:21 +00:00
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize - missingBytes , dict , dictSize ) ;
FUZ_CHECKTEST ( ret > = 0 , " LZ4_decompress_safe_usingDict should have failed : output buffer too small (-%u byte) " , missingBytes ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize - missingBytes ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size (-%u byte) (blockSize=%i) " , missingBytes , blockSize ) ;
2016-08-11 10:18:45 +00:00
} }
2014-10-20 00:08:21 +00:00
2015-04-24 09:15:12 +00:00
/* Compress HC using External dictionary */
2018-09-05 18:25:10 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_HC_continue with an external dictionary " ) ;
2015-04-24 09:15:12 +00:00
dict - = ( FUZ_rand ( & randState ) & 7 ) ; /* even bigger separation */
2014-10-25 19:52:10 +00:00
if ( dict < ( char * ) CNBuffer ) dict = ( char * ) CNBuffer ;
2019-04-18 23:41:27 +00:00
LZ4_loadDictHC ( LZ4dictHC , dict , dictSize ) ;
LZ4_setCompressionLevel ( LZ4dictHC , compressionLevel ) ;
blockContinueCompressedSize = LZ4_compress_HC_continue ( LZ4dictHC , block , compressedBuffer , blockSize , ( int ) compressedBufferSize ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_HC_continue failed " ) ;
2019-04-18 23:41:27 +00:00
FUZ_CHECKTEST ( LZ4dictHC - > internal_donotuse . dirty , " Context should be clean " ) ;
2014-10-20 00:08:21 +00:00
2019-04-09 22:37:59 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_HC_continue with same external dictionary, but output buffer 1 byte too short " ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDictHC ( LZ4dictHC , dict , dictSize ) ;
ret = LZ4_compress_HC_continue ( LZ4dictHC , block , compressedBuffer , blockSize , blockContinueCompressedSize - 1 ) ;
2019-04-09 22:37:59 +00:00
FUZ_CHECKTEST ( ret > 0 , " LZ4_compress_HC_continue using ExtDict should fail : one missing byte for output buffer (expected %i, but result=%i) " , blockContinueCompressedSize , ret ) ;
2019-04-15 18:12:54 +00:00
/* note : context is no longer dirty after a failed compressed block */
2014-10-20 00:08:21 +00:00
2019-04-09 22:37:59 +00:00
FUZ_DISPLAYTEST ( " LZ4_compress_HC_continue with same external dictionary, and output buffer exactly the right size " ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDictHC ( LZ4dictHC , dict , dictSize ) ;
ret = LZ4_compress_HC_continue ( LZ4dictHC , block , compressedBuffer , blockSize , blockContinueCompressedSize ) ;
2019-04-09 22:37:59 +00:00
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_HC_continue size is different : ret(%i) != expected(%i) " , ret , blockContinueCompressedSize ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_HC_continue should work : enough size available within output buffer " ) ;
2019-04-18 23:41:27 +00:00
FUZ_CHECKTEST ( LZ4dictHC - > internal_donotuse . dirty , " Context should be clean " ) ;
2014-10-20 00:08:21 +00:00
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2014-10-20 00:08:21 +00:00
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
2019-04-05 00:03:05 +00:00
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2019-04-18 19:05:50 +00:00
if ( crcCheck ! = crcOrig ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
} }
2014-04-28 20:45:35 +00:00
2018-04-20 19:16:41 +00:00
/* Compress HC using external dictionary stream */
FUZ_DISPLAYTEST ( ) ;
2019-04-19 01:50:51 +00:00
{ LZ4_streamHC_t * const LZ4_streamHC = LZ4_createStreamHC ( ) ;
2018-04-20 19:16:41 +00:00
2019-04-18 23:41:27 +00:00
LZ4_loadDictHC ( LZ4dictHC , dict , dictSize ) ;
2019-04-19 00:12:14 +00:00
LZ4_attach_HC_dictionary ( LZ4_streamHC , LZ4dictHC ) ;
LZ4_setCompressionLevel ( LZ4_streamHC , compressionLevel ) ;
blockContinueCompressedSize = LZ4_compress_HC_continue ( LZ4_streamHC , block , compressedBuffer , blockSize , ( int ) compressedBufferSize ) ;
2018-04-20 19:16:41 +00:00
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_HC_continue with ExtDictCtx failed " ) ;
2019-04-19 00:12:14 +00:00
FUZ_CHECKTEST ( LZ4_streamHC - > internal_donotuse . dirty , " Context should be clean " ) ;
2018-04-20 19:16:41 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-04-19 00:12:14 +00:00
LZ4_resetStreamHC_fast ( LZ4_streamHC , compressionLevel ) ;
LZ4_attach_HC_dictionary ( LZ4_streamHC , LZ4dictHC ) ;
ret = LZ4_compress_HC_continue ( LZ4_streamHC , block , compressedBuffer , blockSize , blockContinueCompressedSize - 1 ) ;
2018-04-20 19:16:41 +00:00
FUZ_CHECKTEST ( ret > 0 , " LZ4_compress_HC_continue using ExtDictCtx should fail : one missing byte for output buffer (%i != %i) " , ret , blockContinueCompressedSize ) ;
2019-04-15 18:12:54 +00:00
/* note : context is no longer dirty after a failed compressed block */
2018-04-20 19:16:41 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-04-19 00:12:14 +00:00
LZ4_resetStreamHC_fast ( LZ4_streamHC , compressionLevel ) ;
LZ4_attach_HC_dictionary ( LZ4_streamHC , LZ4dictHC ) ;
ret = LZ4_compress_HC_continue ( LZ4_streamHC , block , compressedBuffer , blockSize , blockContinueCompressedSize ) ;
2018-04-20 19:16:41 +00:00
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_HC_continue using ExtDictCtx size is different (%i != %i) " , ret , blockContinueCompressedSize ) ;
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_HC_continue using ExtDictCtx should work : enough size available within output buffer " ) ;
2019-04-19 00:12:14 +00:00
FUZ_CHECKTEST ( LZ4_streamHC - > internal_donotuse . dirty , " Context should be clean " ) ;
2018-04-20 19:16:41 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-04-19 00:12:14 +00:00
LZ4_resetStreamHC_fast ( LZ4_streamHC , compressionLevel ) ;
LZ4_attach_HC_dictionary ( LZ4_streamHC , LZ4dictHC ) ;
ret = LZ4_compress_HC_continue ( LZ4_streamHC , block , compressedBuffer , blockSize , blockContinueCompressedSize ) ;
2018-04-20 19:16:41 +00:00
FUZ_CHECKTEST ( ret ! = blockContinueCompressedSize , " LZ4_compress_HC_continue using ExtDictCtx and fast reset size is different (%i != %i) " , ret , blockContinueCompressedSize ) ;
FUZ_CHECKTEST ( ret < = 0 , " LZ4_compress_HC_continue using ExtDictCtx and fast reset should work : enough size available within output buffer " ) ;
2019-04-19 00:12:14 +00:00
FUZ_CHECKTEST ( LZ4_streamHC - > internal_donotuse . dirty , " Context should be clean " ) ;
LZ4_freeStreamHC ( LZ4_streamHC ) ;
2019-04-09 20:55:42 +00:00
}
2018-04-20 19:16:41 +00:00
2019-04-09 20:55:42 +00:00
FUZ_DISPLAYTEST ( ) ;
decodedBuffer [ blockSize ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , blockSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = blockSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
FUZ_CHECKTEST ( decodedBuffer [ blockSize ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " ) ;
{ U32 const crcCheck = XXH32 ( decodedBuffer , ( size_t ) blockSize , 0 ) ;
2019-04-18 19:05:50 +00:00
if ( crcCheck ! = crcOrig ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
} }
2018-04-20 19:16:41 +00:00
2017-03-16 22:10:38 +00:00
/* Compress HC continue destSize */
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2020-08-12 21:39:01 +00:00
{ int const availableSpace = ( int ) ( FUZ_rand ( & randState ) % ( U32 ) blockSize ) + 5 ;
2017-03-16 22:10:38 +00:00
int consumedSize = blockSize ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2019-04-18 23:41:27 +00:00
LZ4_loadDictHC ( LZ4dictHC , dict , dictSize ) ;
LZ4_setCompressionLevel ( LZ4dictHC , compressionLevel ) ;
blockContinueCompressedSize = LZ4_compress_HC_continue_destSize ( LZ4dictHC , block , compressedBuffer , & consumedSize , availableSpace ) ;
2017-03-17 22:11:09 +00:00
DISPLAYLEVEL ( 5 , " LZ4_compress_HC_continue_destSize : compressed %6i/%6i into %6i/%6i at cLevel=%i \n " , consumedSize , blockSize , blockContinueCompressedSize , availableSpace , compressionLevel ) ;
2017-03-16 22:10:38 +00:00
FUZ_CHECKTEST ( blockContinueCompressedSize = = 0 , " LZ4_compress_HC_continue_destSize failed " ) ;
FUZ_CHECKTEST ( blockContinueCompressedSize > availableSpace , " LZ4_compress_HC_continue_destSize write overflow " ) ;
FUZ_CHECKTEST ( consumedSize > blockSize , " LZ4_compress_HC_continue_destSize read overflow " ) ;
2018-03-21 14:14:13 +00:00
FUZ_DISPLAYTEST ( ) ;
2017-03-16 22:10:38 +00:00
decodedBuffer [ consumedSize ] = 0 ;
ret = LZ4_decompress_safe_usingDict ( compressedBuffer , decodedBuffer , blockContinueCompressedSize , consumedSize , dict , dictSize ) ;
FUZ_CHECKTEST ( ret ! = consumedSize , " LZ4_decompress_safe_usingDict did not regenerate original data " ) ;
FUZ_CHECKTEST ( decodedBuffer [ consumedSize ] , " LZ4_decompress_safe_usingDict overrun specified output buffer size " )
2019-04-05 00:03:05 +00:00
{ U32 const crcSrc = XXH32 ( block , ( size_t ) consumedSize , 0 ) ;
U32 const crcDst = XXH32 ( decodedBuffer , ( size_t ) consumedSize , 0 ) ;
2019-04-18 19:05:50 +00:00
if ( crcSrc ! = crcDst ) {
FUZ_findDiff ( block , decodedBuffer ) ;
EXIT_MSG ( " LZ4_decompress_safe_usingDict corrupted decoded data " ) ;
} }
2017-03-16 22:10:38 +00:00
}
2015-04-10 22:42:17 +00:00
/* ***** End of tests *** */
/* Fill stats */
2020-08-12 21:39:01 +00:00
assert ( blockSize > = 0 ) ;
bytes + = ( unsigned ) blockSize ;
assert ( compressedSize > = 0 ) ;
cbytes + = ( unsigned ) compressedSize ;
assert ( HCcompressedSize > = 0 ) ;
hcbytes + = ( unsigned ) HCcompressedSize ;
assert ( blockContinueCompressedSize > = 0 ) ;
ccbytes + = ( unsigned ) blockContinueCompressedSize ;
2014-10-10 19:58:42 +00:00
}
2013-12-30 17:16:52 +00:00
2015-04-12 07:21:35 +00:00
if ( nbCycles < = 1 ) nbCycles = cycleNb ; /* end by time */
bytes + = ! bytes ; /* avoid division by 0 */
2014-10-20 00:08:21 +00:00
printf ( " \r %7u /%7u - " , cycleNb , nbCycles ) ;
2014-10-10 19:58:42 +00:00
printf ( " all tests completed successfully \n " ) ;
printf ( " compression ratio: %0.3f%% \n " , ( double ) cbytes / bytes * 100 ) ;
printf ( " HC compression ratio: %0.3f%% \n " , ( double ) hcbytes / bytes * 100 ) ;
printf ( " ratio with dict: %0.3f%% \n " , ( double ) ccbytes / bytes * 100 ) ;
2014-04-28 22:17:49 +00:00
2015-04-10 22:42:17 +00:00
/* release memory */
2019-04-18 17:38:51 +00:00
free ( CNBuffer ) ;
free ( compressedBuffer ) ;
free ( decodedBuffer ) ;
FUZ_freeLowAddr ( lowAddrBuffer , labSize ) ;
2019-04-18 23:41:27 +00:00
LZ4_freeStreamHC ( LZ4dictHC ) ;
2019-04-18 17:38:51 +00:00
free ( stateLZ4 ) ;
free ( stateLZ4HC ) ;
return result ;
2014-10-10 19:58:42 +00:00
}
2014-10-25 19:52:10 +00:00
2019-05-29 20:33:55 +00:00
# define testInputSize (196 KB)
2019-05-29 18:19:10 +00:00
# define testCompressedSize (130 KB)
2014-10-25 19:52:10 +00:00
# define ringBufferSize (8 KB)
2014-10-10 19:58:42 +00:00
2016-12-28 16:47:10 +00:00
static void FUZ_unitTests ( int compressionLevel )
2014-10-10 19:58:42 +00:00
{
2014-10-18 10:18:14 +00:00
const unsigned testNb = 0 ;
const unsigned seed = 0 ;
const unsigned cycleNb = 0 ;
2019-04-18 23:41:27 +00:00
char * testInput = ( char * ) malloc ( testInputSize ) ;
char * testCompressed = ( char * ) malloc ( testCompressedSize ) ;
char * testVerify = ( char * ) malloc ( testInputSize ) ;
2019-04-18 19:05:50 +00:00
char ringBuffer [ ringBufferSize ] = { 0 } ;
2014-10-25 19:52:10 +00:00
U32 randState = 1 ;
2014-10-18 10:18:14 +00:00
2015-04-24 09:15:12 +00:00
/* Init */
2019-04-18 23:41:27 +00:00
if ( ! testInput | | ! testCompressed | | ! testVerify ) {
EXIT_MSG ( " not enough memory for FUZ_unitTests " ) ;
}
2014-10-18 10:18:14 +00:00
FUZ_fillCompressibleNoiseBuffer ( testInput , testInputSize , 0.50 , & randState ) ;
2015-04-24 09:15:12 +00:00
/* 32-bits address space overflow test */
2014-10-10 19:58:42 +00:00
FUZ_AddressOverflow ( ) ;
2014-10-18 10:18:14 +00:00
2019-04-19 01:50:51 +00:00
/* Test decoding with empty input */
2019-05-29 18:19:10 +00:00
DISPLAYLEVEL ( 3 , " LZ4_decompress_safe() with empty input \n " ) ;
2019-04-19 01:50:51 +00:00
LZ4_decompress_safe ( testCompressed , testVerify , 0 , testInputSize ) ;
/* Test decoding with a one byte input */
2019-05-29 18:19:10 +00:00
DISPLAYLEVEL ( 3 , " LZ4_decompress_safe() with one byte input \n " ) ;
2019-04-19 01:50:51 +00:00
{ char const tmp = ( char ) 0xFF ;
LZ4_decompress_safe ( & tmp , testVerify , 1 , testInputSize ) ;
}
/* Test decoding shortcut edge case */
2019-05-29 18:19:10 +00:00
DISPLAYLEVEL ( 3 , " LZ4_decompress_safe() with shortcut edge case \n " ) ;
2019-04-19 01:50:51 +00:00
{ char tmp [ 17 ] ;
/* 14 bytes of literals, followed by a 14 byte match.
* Should not read beyond the end of the buffer .
* See https : //github.com/lz4/lz4/issues/508. */
* tmp = ( char ) 0xEE ;
memset ( tmp + 1 , 0 , 14 ) ;
tmp [ 15 ] = 14 ;
tmp [ 16 ] = 0 ;
{ int const r = LZ4_decompress_safe ( tmp , testVerify , sizeof ( tmp ) , testInputSize ) ;
FUZ_CHECKTEST ( r > = 0 , " LZ4_decompress_safe() should fail " ) ;
} }
2019-05-29 18:19:10 +00:00
/* in-place compression test */
DISPLAYLEVEL ( 3 , " in-place compression using LZ4_compress_default() : " ) ;
2019-05-29 20:14:52 +00:00
{ int const sampleSize = 65 KB ;
int const maxCSize = LZ4_COMPRESSBOUND ( sampleSize ) ;
int const outSize = LZ4_COMPRESS_INPLACE_BUFFER_SIZE ( maxCSize ) ;
2019-05-30 23:17:47 +00:00
int const startInputIndex = outSize - sampleSize ;
char * const startInput = testCompressed + startInputIndex ;
2019-05-29 18:19:10 +00:00
XXH32_hash_t const crcOrig = XXH32 ( testInput , sampleSize , 0 ) ;
int cSize ;
2019-05-29 20:17:45 +00:00
assert ( outSize < ( int ) testCompressedSize ) ;
2019-05-29 18:19:10 +00:00
memcpy ( startInput , testInput , sampleSize ) ; /* copy at end of buffer */
/* compress in-place */
cSize = LZ4_compress_default ( startInput , testCompressed , sampleSize , maxCSize ) ;
assert ( cSize ! = 0 ) ; /* ensure compression is successful */
assert ( maxCSize < INT_MAX ) ;
2019-05-29 20:14:52 +00:00
assert ( cSize < = maxCSize ) ;
2019-05-29 18:19:10 +00:00
/* decompress and verify */
{ int const dSize = LZ4_decompress_safe ( testCompressed , testVerify , cSize , testInputSize ) ;
2019-05-30 23:17:47 +00:00
assert ( dSize = = sampleSize ) ; /* correct size */
2019-05-29 18:19:10 +00:00
{ XXH32_hash_t const crcCheck = XXH32 ( testVerify , ( size_t ) dSize , 0 ) ;
assert ( crcCheck = = crcOrig ) ;
} } }
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2019-05-30 23:17:47 +00:00
/* in-place decompression test */
DISPLAYLEVEL ( 3 , " in-place decompression, limit case: " ) ;
{ int const sampleSize = 65 KB ;
FUZ_fillCompressibleNoiseBuffer ( testInput , sampleSize , 0.0 , & randState ) ;
memset ( testInput , 0 , 267 ) ; /* calculated exactly so that compressedSize == originalSize-1 */
{ XXH64_hash_t const crcOrig = XXH64 ( testInput , sampleSize , 0 ) ;
int const cSize = LZ4_compress_default ( testInput , testCompressed , sampleSize , testCompressedSize ) ;
assert ( cSize = = sampleSize - 1 ) ; /* worst case for in-place decompression */
{ int const bufferSize = LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE ( sampleSize ) ;
int const startInputIndex = bufferSize - cSize ;
char * const startInput = testVerify + startInputIndex ;
memcpy ( startInput , testCompressed , cSize ) ;
/* decompress and verify */
{ int const dSize = LZ4_decompress_safe ( startInput , testVerify , cSize , sampleSize ) ;
assert ( dSize = = sampleSize ) ; /* correct size */
{ XXH64_hash_t const crcCheck = XXH64 ( testVerify , ( size_t ) dSize , 0 ) ;
assert ( crcCheck = = crcOrig ) ;
} } } } }
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2015-04-24 09:15:12 +00:00
/* LZ4 streaming tests */
2019-04-18 23:41:27 +00:00
{ LZ4_stream_t streamingState ;
2014-10-25 19:52:10 +00:00
U64 crcOrig ;
int result ;
2015-04-24 09:15:12 +00:00
/* Allocation test */
2019-04-18 23:41:27 +00:00
{ LZ4_stream_t * const statePtr = LZ4_createStream ( ) ;
FUZ_CHECKTEST ( statePtr = = NULL , " LZ4_createStream() allocation failed " ) ;
LZ4_freeStream ( statePtr ) ;
}
2014-10-25 19:52:10 +00:00
2015-04-24 09:15:12 +00:00
/* simple compression test */
2014-10-25 19:52:10 +00:00
crcOrig = XXH64 ( testInput , testCompressedSize , 0 ) ;
2019-04-05 19:54:13 +00:00
LZ4_initStream ( & streamingState , sizeof ( streamingState ) ) ;
2016-11-12 16:48:42 +00:00
result = LZ4_compress_fast_continue ( & streamingState , testInput , testCompressed , testCompressedSize , testCompressedSize - 1 , 1 ) ;
2017-03-08 08:13:28 +00:00
FUZ_CHECKTEST ( result = = 0 , " LZ4_compress_fast_continue() compression failed! " ) ;
2014-10-25 19:52:10 +00:00
result = LZ4_decompress_safe ( testCompressed , testVerify , result , testCompressedSize ) ;
FUZ_CHECKTEST ( result ! = ( int ) testCompressedSize , " LZ4_decompress_safe() decompression failed " ) ;
2016-11-14 04:50:58 +00:00
{ U64 const crcNew = XXH64 ( testVerify , testCompressedSize , 0 ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe() decompression corruption " ) ; }
2014-10-25 19:52:10 +00:00
2015-04-24 09:15:12 +00:00
/* ring buffer test */
2016-08-11 10:18:45 +00:00
{ XXH64_state_t xxhOrig ;
2018-04-27 04:06:37 +00:00
XXH64_state_t xxhNewSafe , xxhNewFast ;
LZ4_streamDecode_t decodeStateSafe , decodeStateFast ;
2014-10-25 19:52:10 +00:00
const U32 maxMessageSizeLog = 10 ;
const U32 maxMessageSizeMask = ( 1 < < maxMessageSizeLog ) - 1 ;
U32 messageSize = ( FUZ_rand ( & randState ) & maxMessageSizeMask ) + 1 ;
U32 iNext = 0 ;
U32 rNext = 0 ;
U32 dNext = 0 ;
const U32 dBufferSize = ringBufferSize + maxMessageSizeMask ;
XXH64_reset ( & xxhOrig , 0 ) ;
2018-04-27 04:06:37 +00:00
XXH64_reset ( & xxhNewSafe , 0 ) ;
XXH64_reset ( & xxhNewFast , 0 ) ;
2018-09-18 18:29:31 +00:00
LZ4_resetStream_fast ( & streamingState ) ;
2018-04-27 04:06:37 +00:00
LZ4_setStreamDecode ( & decodeStateSafe , NULL , 0 ) ;
LZ4_setStreamDecode ( & decodeStateFast , NULL , 0 ) ;
2014-10-25 19:52:10 +00:00
2016-08-11 10:18:45 +00:00
while ( iNext + messageSize < testCompressedSize ) {
2019-04-18 19:05:50 +00:00
int compressedSize ;
2014-10-25 19:52:10 +00:00
XXH64_update ( & xxhOrig , testInput + iNext , messageSize ) ;
crcOrig = XXH64_digest ( & xxhOrig ) ;
memcpy ( ringBuffer + rNext , testInput + iNext , messageSize ) ;
2019-05-29 18:19:10 +00:00
compressedSize = LZ4_compress_fast_continue ( & streamingState , ringBuffer + rNext , testCompressed , ( int ) messageSize , testCompressedSize - ringBufferSize , 1 ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( compressedSize = = 0 , " LZ4_compress_fast_continue() compression failed " ) ;
2014-10-25 19:52:10 +00:00
2019-05-29 18:19:10 +00:00
result = LZ4_decompress_safe_continue ( & decodeStateSafe , testCompressed , testVerify + dNext , compressedSize , ( int ) messageSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( result ! = ( int ) messageSize , " ringBuffer : LZ4_decompress_safe_continue() test failed " ) ;
2014-10-25 19:52:10 +00:00
2018-04-27 04:06:37 +00:00
XXH64_update ( & xxhNewSafe , testVerify + dNext , messageSize ) ;
{ U64 const crcNew = XXH64_digest ( & xxhNewSafe ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe_continue() decompression corruption " ) ; }
2019-05-29 18:19:10 +00:00
result = LZ4_decompress_fast_continue ( & decodeStateFast , testCompressed , testVerify + dNext , ( int ) messageSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( result ! = compressedSize , " ringBuffer : LZ4_decompress_fast_continue() test failed " ) ;
XXH64_update ( & xxhNewFast , testVerify + dNext , messageSize ) ;
{ U64 const crcNew = XXH64_digest ( & xxhNewFast ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_fast_continue() decompression corruption " ) ; }
2014-10-25 19:52:10 +00:00
2015-04-24 09:15:12 +00:00
/* prepare next message */
2014-10-25 19:52:10 +00:00
iNext + = messageSize ;
rNext + = messageSize ;
dNext + = messageSize ;
messageSize = ( FUZ_rand ( & randState ) & maxMessageSizeMask ) + 1 ;
if ( rNext + messageSize > ringBufferSize ) rNext = 0 ;
if ( dNext + messageSize > dBufferSize ) dNext = 0 ;
}
}
}
2015-04-24 09:15:12 +00:00
/* LZ4 HC streaming tests */
2019-01-09 20:09:52 +00:00
{ LZ4_streamHC_t sHC ; /* statically allocated */
2014-10-18 10:18:14 +00:00
U64 crcOrig ;
int result ;
2019-04-09 20:55:42 +00:00
LZ4_initStreamHC ( & sHC , sizeof ( sHC ) ) ;
2014-10-18 10:18:14 +00:00
2015-04-24 09:15:12 +00:00
/* Allocation test */
2019-01-09 20:09:52 +00:00
DISPLAYLEVEL ( 3 , " Basic HC allocation : " ) ;
{ LZ4_streamHC_t * const sp = LZ4_createStreamHC ( ) ;
FUZ_CHECKTEST ( sp = = NULL , " LZ4_createStreamHC() allocation failed " ) ;
LZ4_freeStreamHC ( sp ) ;
}
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2014-10-18 10:18:14 +00:00
2015-04-24 09:15:12 +00:00
/* simple HC compression test */
2019-01-09 20:09:52 +00:00
DISPLAYLEVEL ( 3 , " Simple HC round-trip : " ) ;
{ U64 const crc64 = XXH64 ( testInput , testCompressedSize , 0 ) ;
2019-04-09 20:55:42 +00:00
LZ4_setCompressionLevel ( & sHC , compressionLevel ) ;
2019-01-09 20:09:52 +00:00
result = LZ4_compress_HC_continue ( & sHC , testInput , testCompressed , testCompressedSize , testCompressedSize - 1 ) ;
FUZ_CHECKTEST ( result = = 0 , " LZ4_compressHC_limitedOutput_continue() compression failed " ) ;
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2014-10-18 10:18:14 +00:00
2019-01-09 20:09:52 +00:00
result = LZ4_decompress_safe ( testCompressed , testVerify , result , testCompressedSize ) ;
FUZ_CHECKTEST ( result ! = ( int ) testCompressedSize , " LZ4_decompress_safe() decompression failed " ) ;
{ U64 const crcNew = XXH64 ( testVerify , testCompressedSize , 0 ) ;
FUZ_CHECKTEST ( crc64 ! = crcNew , " LZ4_decompress_safe() decompression corruption " ) ;
} }
DISPLAYLEVEL ( 3 , " OK \n " ) ;
/* long sequence test */
DISPLAYLEVEL ( 3 , " Long sequence HC test : " ) ;
{ size_t const blockSize = 1 MB ;
size_t const targetSize = 4116 ; /* size carefully selected to trigger an overflow */
void * const block = malloc ( blockSize ) ;
void * const dstBlock = malloc ( targetSize + 1 ) ;
BYTE const sentinel = 101 ;
int srcSize ;
assert ( block ! = NULL ) ; assert ( dstBlock ! = NULL ) ;
memset ( block , 0 , blockSize ) ;
( ( char * ) dstBlock ) [ targetSize ] = sentinel ;
2019-04-09 20:55:42 +00:00
LZ4_resetStreamHC_fast ( & sHC , 3 ) ;
2019-01-09 20:09:52 +00:00
assert ( blockSize < INT_MAX ) ;
srcSize = ( int ) blockSize ;
2019-01-09 21:38:33 +00:00
assert ( targetSize < INT_MAX ) ;
2019-01-09 21:45:42 +00:00
result = LZ4_compress_HC_destSize ( & sHC , ( const char * ) block , ( char * ) dstBlock , & srcSize , ( int ) targetSize , 3 ) ;
2019-01-09 21:38:33 +00:00
DISPLAYLEVEL ( 4 , " cSize=%i; readSize=%i; " , result , srcSize ) ;
FUZ_CHECKTEST ( result ! = 4116 , " LZ4_compress_HC_destSize() : compression must fill dstBuffer completely, but no more ! " ) ;
2019-01-09 20:09:52 +00:00
FUZ_CHECKTEST ( ( ( char * ) dstBlock ) [ targetSize ] ! = sentinel , " LZ4_compress_HC_destSize() " )
2019-04-05 00:03:05 +00:00
LZ4_resetStreamHC_fast ( & sHC , 3 ) ; /* make sure the context is clean after the test */
2019-01-09 20:09:52 +00:00
free ( block ) ;
free ( dstBlock ) ;
}
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2014-10-18 10:18:14 +00:00
2015-04-24 09:15:12 +00:00
/* simple dictionary HC compression test */
2019-01-09 20:09:52 +00:00
DISPLAYLEVEL ( 3 , " HC dictionary compression test : " ) ;
{ U64 const crc64 = XXH64 ( testInput + 64 KB , testCompressedSize , 0 ) ;
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
LZ4_loadDictHC ( & sHC , testInput , 64 KB ) ;
2019-05-29 20:33:55 +00:00
{ int const cSize = LZ4_compress_HC_continue ( & sHC , testInput + 64 KB , testCompressed , testCompressedSize , testCompressedSize - 1 ) ;
FUZ_CHECKTEST ( cSize = = 0 , " LZ4_compressHC_limitedOutput_continue() dictionary compression failed : @return = %i " , cSize ) ;
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
{ int const dSize = LZ4_decompress_safe_usingDict ( testCompressed , testVerify , cSize , testCompressedSize , testInput , 64 KB ) ;
FUZ_CHECKTEST ( dSize ! = ( int ) testCompressedSize , " LZ4_decompress_safe() simple dictionary decompression test failed " ) ;
} }
2019-01-09 20:09:52 +00:00
{ U64 const crcNew = XXH64 ( testVerify , testCompressedSize , 0 ) ;
FUZ_CHECKTEST ( crc64 ! = crcNew , " LZ4_decompress_safe() simple dictionary decompression test : corruption " ) ;
} }
DISPLAYLEVEL ( 3 , " OK \n " ) ;
2014-10-18 10:18:14 +00:00
2015-04-10 22:42:17 +00:00
/* multiple HC compression test with dictionary */
2016-08-11 10:18:45 +00:00
{ int result1 , result2 ;
2014-10-18 10:18:14 +00:00
int segSize = testCompressedSize / 2 ;
2019-05-29 20:33:55 +00:00
XXH64_hash_t const crc64 = ( ( void ) assert ( ( unsigned ) segSize + testCompressedSize < testInputSize ) ,
XXH64 ( testInput + segSize , testCompressedSize , 0 ) ) ;
2018-09-20 18:47:30 +00:00
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
2014-10-18 10:18:14 +00:00
LZ4_loadDictHC ( & sHC , testInput , segSize ) ;
2016-11-12 16:48:42 +00:00
result1 = LZ4_compress_HC_continue ( & sHC , testInput + segSize , testCompressed , segSize , segSize - 1 ) ;
2014-10-20 23:12:55 +00:00
FUZ_CHECKTEST ( result1 = = 0 , " LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i " , result1 ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2019-04-13 00:40:23 +00:00
result2 = LZ4_compress_HC_continue ( & sHC , testInput + 2 * ( size_t ) segSize , testCompressed + result1 , segSize , segSize - 1 ) ;
2014-10-20 23:12:55 +00:00
FUZ_CHECKTEST ( result2 = = 0 , " LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i " , result2 ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2014-10-18 10:18:14 +00:00
result = LZ4_decompress_safe_usingDict ( testCompressed , testVerify , result1 , segSize , testInput , segSize ) ;
FUZ_CHECKTEST ( result ! = segSize , " LZ4_decompress_safe() dictionary decompression part 1 failed " ) ;
result = LZ4_decompress_safe_usingDict ( testCompressed + result1 , testVerify + segSize , result2 , segSize , testInput , 2 * segSize ) ;
FUZ_CHECKTEST ( result ! = segSize , " LZ4_decompress_safe() dictionary decompression part 2 failed " ) ;
2019-05-29 20:33:55 +00:00
{ XXH64_hash_t const crcNew = XXH64 ( testVerify , testCompressedSize , 0 ) ;
2019-01-09 20:09:52 +00:00
FUZ_CHECKTEST ( crc64 ! = crcNew , " LZ4_decompress_safe() dictionary decompression corruption " ) ;
} }
2014-10-18 10:18:14 +00:00
2015-04-24 09:15:12 +00:00
/* remote dictionary HC compression test */
2019-01-09 20:09:52 +00:00
{ U64 const crc64 = XXH64 ( testInput + 64 KB , testCompressedSize , 0 ) ;
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
LZ4_loadDictHC ( & sHC , testInput , 32 KB ) ;
result = LZ4_compress_HC_continue ( & sHC , testInput + 64 KB , testCompressed , testCompressedSize , testCompressedSize - 1 ) ;
FUZ_CHECKTEST ( result = = 0 , " LZ4_compressHC_limitedOutput_continue() remote dictionary failed : result = %i " , result ) ;
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
result = LZ4_decompress_safe_usingDict ( testCompressed , testVerify , result , testCompressedSize , testInput , 32 KB ) ;
FUZ_CHECKTEST ( result ! = ( int ) testCompressedSize , " LZ4_decompress_safe_usingDict() decompression failed following remote dictionary HC compression test " ) ;
{ U64 const crcNew = XXH64 ( testVerify , testCompressedSize , 0 ) ;
FUZ_CHECKTEST ( crc64 ! = crcNew , " LZ4_decompress_safe_usingDict() decompression corruption " ) ;
} }
2014-10-20 23:12:55 +00:00
2015-04-10 22:42:17 +00:00
/* multiple HC compression with ext. dictionary */
2016-08-11 10:18:45 +00:00
{ XXH64_state_t crcOrigState ;
2014-10-20 23:12:55 +00:00
XXH64_state_t crcNewState ;
const char * dict = testInput + 3 ;
2019-05-30 23:17:47 +00:00
size_t dictSize = ( FUZ_rand ( & randState ) & 8191 ) ;
2014-10-20 23:12:55 +00:00
char * dst = testVerify ;
2019-05-30 23:17:47 +00:00
size_t segStart = dictSize + 7 ;
size_t segSize = ( FUZ_rand ( & randState ) & 8191 ) ;
2014-10-20 23:12:55 +00:00
int segNb = 1 ;
2018-09-20 18:47:30 +00:00
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
2019-05-30 23:17:47 +00:00
LZ4_loadDictHC ( & sHC , dict , ( int ) dictSize ) ;
2014-10-20 23:12:55 +00:00
XXH64_reset ( & crcOrigState , 0 ) ;
XXH64_reset ( & crcNewState , 0 ) ;
2016-08-11 10:18:45 +00:00
while ( segStart + segSize < testInputSize ) {
2014-10-20 23:12:55 +00:00
XXH64_update ( & crcOrigState , testInput + segStart , segSize ) ;
crcOrig = XXH64_digest ( & crcOrigState ) ;
2019-05-30 23:17:47 +00:00
assert ( segSize < = INT_MAX ) ;
result = LZ4_compress_HC_continue ( & sHC , testInput + segStart , testCompressed , ( int ) segSize , LZ4_compressBound ( ( int ) segSize ) ) ;
2014-10-20 23:12:55 +00:00
FUZ_CHECKTEST ( result = = 0 , " LZ4_compressHC_limitedOutput_continue() dictionary compression failed : result = %i " , result ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2014-10-20 23:12:55 +00:00
2019-05-30 23:17:47 +00:00
result = LZ4_decompress_safe_usingDict ( testCompressed , dst , result , ( int ) segSize , dict , ( int ) dictSize ) ;
FUZ_CHECKTEST ( result ! = ( int ) segSize , " LZ4_decompress_safe_usingDict() dictionary decompression part %i failed " , ( int ) segNb ) ;
2014-10-20 23:12:55 +00:00
XXH64_update ( & crcNewState , dst , segSize ) ;
2016-11-14 04:50:58 +00:00
{ U64 const crcNew = XXH64_digest ( & crcNewState ) ;
if ( crcOrig ! = crcNew ) FUZ_findDiff ( dst , testInput + segStart ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe_usingDict() part %i corruption " , segNb ) ;
2014-10-25 19:52:10 +00:00
}
2014-10-20 23:12:55 +00:00
dict = dst ;
dictSize = segSize ;
2019-05-30 23:17:47 +00:00
dst + = segSize + 1 ;
2014-10-20 23:12:55 +00:00
segNb + + ;
2019-05-30 23:17:47 +00:00
segStart + = segSize + ( FUZ_rand ( & randState ) & 0xF ) + 1 ;
2014-10-20 23:12:55 +00:00
segSize = ( FUZ_rand ( & randState ) & 8191 ) ;
2019-05-30 23:17:47 +00:00
} }
2014-10-25 19:52:10 +00:00
2015-04-10 22:42:17 +00:00
/* ring buffer test */
2016-08-11 10:18:45 +00:00
{ XXH64_state_t xxhOrig ;
2018-04-27 04:06:37 +00:00
XXH64_state_t xxhNewSafe , xxhNewFast ;
LZ4_streamDecode_t decodeStateSafe , decodeStateFast ;
2014-10-25 19:52:10 +00:00
const U32 maxMessageSizeLog = 10 ;
const U32 maxMessageSizeMask = ( 1 < < maxMessageSizeLog ) - 1 ;
U32 messageSize = ( FUZ_rand ( & randState ) & maxMessageSizeMask ) + 1 ;
U32 iNext = 0 ;
U32 rNext = 0 ;
U32 dNext = 0 ;
const U32 dBufferSize = ringBufferSize + maxMessageSizeMask ;
XXH64_reset ( & xxhOrig , 0 ) ;
2018-04-27 04:06:37 +00:00
XXH64_reset ( & xxhNewSafe , 0 ) ;
XXH64_reset ( & xxhNewFast , 0 ) ;
2018-09-20 18:47:30 +00:00
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
2018-04-27 04:06:37 +00:00
LZ4_setStreamDecode ( & decodeStateSafe , NULL , 0 ) ;
LZ4_setStreamDecode ( & decodeStateFast , NULL , 0 ) ;
2014-10-25 19:52:10 +00:00
2016-08-11 10:18:45 +00:00
while ( iNext + messageSize < testCompressedSize ) {
2019-04-18 19:05:50 +00:00
int compressedSize ;
2014-10-25 19:52:10 +00:00
XXH64_update ( & xxhOrig , testInput + iNext , messageSize ) ;
crcOrig = XXH64_digest ( & xxhOrig ) ;
memcpy ( ringBuffer + rNext , testInput + iNext , messageSize ) ;
2019-05-30 23:17:47 +00:00
assert ( messageSize < INT_MAX ) ;
compressedSize = LZ4_compress_HC_continue ( & sHC , ringBuffer + rNext , testCompressed , ( int ) messageSize , testCompressedSize - ringBufferSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( compressedSize = = 0 , " LZ4_compress_HC_continue() compression failed " ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2018-04-27 04:06:37 +00:00
2019-05-30 23:17:47 +00:00
assert ( messageSize < INT_MAX ) ;
result = LZ4_decompress_safe_continue ( & decodeStateSafe , testCompressed , testVerify + dNext , compressedSize , ( int ) messageSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( result ! = ( int ) messageSize , " ringBuffer : LZ4_decompress_safe_continue() test failed " ) ;
2014-10-25 19:52:10 +00:00
2018-04-27 04:06:37 +00:00
XXH64_update ( & xxhNewSafe , testVerify + dNext , messageSize ) ;
{ U64 const crcNew = XXH64_digest ( & xxhNewSafe ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe_continue() decompression corruption " ) ; }
2014-10-25 19:52:10 +00:00
2019-05-30 23:17:47 +00:00
assert ( messageSize < INT_MAX ) ;
result = LZ4_decompress_fast_continue ( & decodeStateFast , testCompressed , testVerify + dNext , ( int ) messageSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( result ! = compressedSize , " ringBuffer : LZ4_decompress_fast_continue() test failed " ) ;
XXH64_update ( & xxhNewFast , testVerify + dNext , messageSize ) ;
{ U64 const crcNew = XXH64_digest ( & xxhNewFast ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_fast_continue() decompression corruption " ) ; }
2014-10-25 19:52:10 +00:00
2016-08-11 10:18:45 +00:00
/* prepare next message */
2014-10-25 19:52:10 +00:00
iNext + = messageSize ;
rNext + = messageSize ;
dNext + = messageSize ;
messageSize = ( FUZ_rand ( & randState ) & maxMessageSizeMask ) + 1 ;
if ( rNext + messageSize > ringBufferSize ) rNext = 0 ;
if ( dNext + messageSize > dBufferSize ) dNext = 0 ;
}
}
2018-05-02 19:56:37 +00:00
/* Ring buffer test : Non synchronized decoder */
/* This test uses minimum amount of memory required to setup a decoding ring buffer
* while being unsynchronized with encoder
* ( no assumption done on how the data is encoded , it just follows LZ4 format specification ) .
* This size is documented in lz4 . h , and is LZ4_decoderRingBufferSize ( maxBlockSize ) .
*/
2016-08-11 10:18:45 +00:00
{ XXH64_state_t xxhOrig ;
2018-04-27 04:06:37 +00:00
XXH64_state_t xxhNewSafe , xxhNewFast ;
LZ4_streamDecode_t decodeStateSafe , decodeStateFast ;
2018-05-02 19:56:37 +00:00
const int maxMessageSizeLog = 12 ;
const int maxMessageSize = 1 < < maxMessageSizeLog ;
const int maxMessageSizeMask = maxMessageSize - 1 ;
int messageSize ;
2014-11-04 09:04:37 +00:00
U32 totalMessageSize = 0 ;
2018-05-02 19:56:37 +00:00
const int dBufferSize = LZ4_decoderRingBufferSize ( maxMessageSize ) ;
char * const ringBufferSafe = testVerify ;
char * const ringBufferFast = testVerify + dBufferSize + 1 ; /* used by LZ4_decompress_fast_continue */
int iNext = 0 ;
int dNext = 0 ;
2018-04-27 04:06:37 +00:00
int compressedSize ;
2014-11-04 09:04:37 +00:00
2019-04-18 23:06:02 +00:00
assert ( ( size_t ) dBufferSize * 2 + 1 < testInputSize ) ; /* space used by ringBufferSafe and ringBufferFast */
2014-11-04 09:04:37 +00:00
XXH64_reset ( & xxhOrig , 0 ) ;
2018-04-27 04:06:37 +00:00
XXH64_reset ( & xxhNewSafe , 0 ) ;
XXH64_reset ( & xxhNewFast , 0 ) ;
2018-09-20 18:47:30 +00:00
LZ4_resetStreamHC_fast ( & sHC , compressionLevel ) ;
2018-04-27 04:06:37 +00:00
LZ4_setStreamDecode ( & decodeStateSafe , NULL , 0 ) ;
LZ4_setStreamDecode ( & decodeStateFast , NULL , 0 ) ;
2014-11-04 09:04:37 +00:00
2018-05-02 19:56:37 +00:00
# define BSIZE1 (dBufferSize - (maxMessageSize-1))
2015-04-24 09:15:12 +00:00
/* first block */
2018-05-02 19:56:37 +00:00
messageSize = BSIZE1 ; /* note : we cheat a bit here, in theory no message should be > maxMessageSize. We just want to fill the decoding ring buffer once. */
2019-04-18 19:05:50 +00:00
XXH64_update ( & xxhOrig , testInput + iNext , ( size_t ) messageSize ) ;
2017-12-22 10:54:43 +00:00
crcOrig = XXH64_digest ( & xxhOrig ) ;
2018-04-27 04:06:37 +00:00
compressedSize = LZ4_compress_HC_continue ( & sHC , testInput + iNext , testCompressed , messageSize , testCompressedSize - ringBufferSize ) ;
FUZ_CHECKTEST ( compressedSize = = 0 , " LZ4_compress_HC_continue() compression failed " ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2018-04-27 04:06:37 +00:00
2018-05-02 19:56:37 +00:00
result = LZ4_decompress_safe_continue ( & decodeStateSafe , testCompressed , ringBufferSafe + dNext , compressedSize , messageSize ) ;
FUZ_CHECKTEST ( result ! = messageSize , " 64K D.ringBuffer : LZ4_decompress_safe_continue() test failed " ) ;
2017-12-22 10:54:43 +00:00
2019-05-30 23:17:47 +00:00
XXH64_update ( & xxhNewSafe , ringBufferSafe + dNext , ( size_t ) messageSize ) ;
2018-04-27 04:06:37 +00:00
{ U64 const crcNew = XXH64_digest ( & xxhNewSafe ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe_continue() decompression corruption " ) ; }
2017-12-22 10:54:43 +00:00
2018-05-02 19:56:37 +00:00
result = LZ4_decompress_fast_continue ( & decodeStateFast , testCompressed , ringBufferFast + dNext , messageSize ) ;
2018-04-27 04:06:37 +00:00
FUZ_CHECKTEST ( result ! = compressedSize , " 64K D.ringBuffer : LZ4_decompress_fast_continue() test failed " ) ;
2019-05-30 23:17:47 +00:00
XXH64_update ( & xxhNewFast , ringBufferFast + dNext , ( size_t ) messageSize ) ;
2018-04-27 04:06:37 +00:00
{ U64 const crcNew = XXH64_digest ( & xxhNewFast ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_fast_continue() decompression corruption " ) ; }
2017-12-22 10:54:43 +00:00
2018-05-02 19:56:37 +00:00
/* prepare second message */
2017-12-22 10:54:43 +00:00
dNext + = messageSize ;
2019-04-13 00:40:23 +00:00
assert ( messageSize > = 0 ) ;
totalMessageSize + = ( unsigned ) messageSize ;
2018-05-02 19:56:37 +00:00
messageSize = maxMessageSize ;
iNext = BSIZE1 + 1 ;
assert ( BSIZE1 > = 65535 ) ;
memcpy ( testInput + iNext , testInput + ( BSIZE1 - 65535 ) , messageSize ) ; /* will generate a match at max distance == 65535 */
FUZ_CHECKTEST ( dNext + messageSize < = dBufferSize , " Ring buffer test : second message should require restarting from beginning " ) ;
dNext = 0 ;
2015-04-24 09:15:12 +00:00
2016-08-11 10:18:45 +00:00
while ( totalMessageSize < 9 MB ) {
2019-05-30 23:17:47 +00:00
XXH64_update ( & xxhOrig , testInput + iNext , ( size_t ) messageSize ) ;
2014-11-04 09:04:37 +00:00
crcOrig = XXH64_digest ( & xxhOrig ) ;
2018-04-27 04:06:37 +00:00
compressedSize = LZ4_compress_HC_continue ( & sHC , testInput + iNext , testCompressed , messageSize , testCompressedSize - ringBufferSize ) ;
FUZ_CHECKTEST ( compressedSize = = 0 , " LZ4_compress_HC_continue() compression failed " ) ;
2018-09-20 18:47:30 +00:00
FUZ_CHECKTEST ( sHC . internal_donotuse . dirty , " Context should be clean " ) ;
2018-05-02 19:56:37 +00:00
DISPLAYLEVEL ( 5 , " compressed %i bytes to %i bytes \n " , messageSize , compressedSize ) ;
/* test LZ4_decompress_safe_continue */
assert ( dNext < dBufferSize ) ;
assert ( dBufferSize - dNext > = maxMessageSize ) ;
result = LZ4_decompress_safe_continue ( & decodeStateSafe ,
testCompressed , ringBufferSafe + dNext ,
2018-05-02 20:57:33 +00:00
compressedSize , dBufferSize - dNext ) ; /* works without knowing messageSize, under assumption that messageSize <= maxMessageSize */
2018-05-02 19:56:37 +00:00
FUZ_CHECKTEST ( result ! = messageSize , " D.ringBuffer : LZ4_decompress_safe_continue() test failed " ) ;
2019-05-30 23:17:47 +00:00
XXH64_update ( & xxhNewSafe , ringBufferSafe + dNext , ( size_t ) messageSize ) ;
2018-04-27 04:06:37 +00:00
{ U64 const crcNew = XXH64_digest ( & xxhNewSafe ) ;
2018-05-02 19:56:37 +00:00
if ( crcOrig ! = crcNew ) FUZ_findDiff ( testInput + iNext , ringBufferSafe + dNext ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_safe_continue() decompression corruption during D.ringBuffer test " ) ;
2018-04-27 04:06:37 +00:00
}
2014-11-04 09:04:37 +00:00
2018-05-02 19:56:37 +00:00
/* test LZ4_decompress_fast_continue in its own buffer ringBufferFast */
result = LZ4_decompress_fast_continue ( & decodeStateFast , testCompressed , ringBufferFast + dNext , messageSize ) ;
FUZ_CHECKTEST ( result ! = compressedSize , " D.ringBuffer : LZ4_decompress_fast_continue() test failed " ) ;
2019-05-30 23:17:47 +00:00
XXH64_update ( & xxhNewFast , ringBufferFast + dNext , ( size_t ) messageSize ) ;
2018-04-27 04:06:37 +00:00
{ U64 const crcNew = XXH64_digest ( & xxhNewFast ) ;
2018-05-02 19:56:37 +00:00
if ( crcOrig ! = crcNew ) FUZ_findDiff ( testInput + iNext , ringBufferFast + dNext ) ;
FUZ_CHECKTEST ( crcOrig ! = crcNew , " LZ4_decompress_fast_continue() decompression corruption during D.ringBuffer test " ) ;
2016-11-14 04:50:58 +00:00
}
2018-05-02 19:56:37 +00:00
2015-03-22 12:42:00 +00:00
/* prepare next message */
2014-11-04 09:04:37 +00:00
dNext + = messageSize ;
2019-05-30 23:17:47 +00:00
assert ( messageSize > = 0 ) ;
totalMessageSize + = ( unsigned ) messageSize ;
2014-11-04 09:04:37 +00:00
messageSize = ( FUZ_rand ( & randState ) & maxMessageSizeMask ) + 1 ;
iNext = ( FUZ_rand ( & randState ) & 65535 ) ;
2018-05-02 19:56:37 +00:00
if ( dNext + maxMessageSize > dBufferSize ) dNext = 0 ;
2014-11-04 09:04:37 +00:00
}
}
2014-10-18 10:18:14 +00:00
}
2019-04-18 23:41:27 +00:00
/* clean up */
free ( testInput ) ;
free ( testCompressed ) ;
free ( testVerify ) ;
2016-12-28 16:47:10 +00:00
printf ( " All unit tests completed successfully compressionLevel=%d \n " , compressionLevel ) ;
2014-10-18 10:18:14 +00:00
return ;
2013-12-30 17:16:52 +00:00
}
2014-04-29 20:39:08 +00:00
2019-05-30 23:17:47 +00:00
/* =======================================
* CLI
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2016-11-13 01:14:57 +00:00
static int FUZ_usage ( const char * programName )
2014-04-29 20:39:08 +00:00
{
DISPLAY ( " Usage : \n " ) ;
DISPLAY ( " %s [args] \n " , programName ) ;
DISPLAY ( " \n " ) ;
DISPLAY ( " Arguments : \n " ) ;
DISPLAY ( " -i# : Nb of tests (default:%i) \n " , NB_ATTEMPTS ) ;
2015-04-12 15:40:58 +00:00
DISPLAY ( " -T# : Duration of tests, in seconds (default: use Nb of tests) \n " ) ;
2014-04-29 20:39:08 +00:00
DISPLAY ( " -s# : Select seed (default:prompt user) \n " ) ;
2014-05-19 23:40:29 +00:00
DISPLAY ( " -t# : Select starting test number (default:0) \n " ) ;
2014-10-10 19:58:42 +00:00
DISPLAY ( " -P# : Select compressibility in %% (default:%i%%) \n " , FUZ_COMPRESSIBILITY_DEFAULT ) ;
2014-06-09 01:42:39 +00:00
DISPLAY ( " -v : verbose \n " ) ;
2014-10-10 19:58:42 +00:00
DISPLAY ( " -p : pause at the end \n " ) ;
2014-04-29 20:39:08 +00:00
DISPLAY ( " -h : display help and exit \n " ) ;
return 0 ;
}
2016-11-13 01:14:57 +00:00
int main ( int argc , const char * * argv )
2014-10-09 21:15:57 +00:00
{
2016-11-13 01:14:57 +00:00
U32 seed = 0 ;
int seedset = 0 ;
2014-04-29 20:39:08 +00:00
int argNb ;
2019-06-30 20:59:49 +00:00
unsigned nbTests = NB_ATTEMPTS ;
unsigned testNb = 0 ;
2014-04-29 22:44:49 +00:00
int proba = FUZ_COMPRESSIBILITY_DEFAULT ;
2016-12-21 09:39:27 +00:00
int use_pause = 0 ;
2016-11-13 01:14:57 +00:00
const char * programName = argv [ 0 ] ;
2015-04-10 22:42:17 +00:00
U32 duration = 0 ;
2014-04-29 20:39:08 +00:00
2015-04-10 22:42:17 +00:00
/* Check command line */
2016-08-11 10:18:45 +00:00
for ( argNb = 1 ; argNb < argc ; argNb + + ) {
2016-11-13 01:14:57 +00:00
const char * argument = argv [ argNb ] ;
2014-04-29 20:39:08 +00:00
if ( ! argument ) continue ; // Protection if argument empty
// Decode command (note : aggregated commands are allowed)
2016-08-11 10:18:45 +00:00
if ( argument [ 0 ] = = ' - ' ) {
2016-12-21 09:39:27 +00:00
if ( ! strcmp ( argument , " --no-prompt " ) ) { use_pause = 0 ; seedset = 1 ; g_displayLevel = 1 ; continue ; }
2014-10-18 12:27:32 +00:00
argument + + ;
2014-04-29 20:39:08 +00:00
2016-08-11 10:18:45 +00:00
while ( * argument ! = 0 ) {
2014-04-29 20:39:08 +00:00
switch ( * argument )
{
2014-10-10 19:58:42 +00:00
case ' h ' : /* display help */
2014-10-19 15:06:33 +00:00
return FUZ_usage ( programName ) ;
2014-10-10 19:58:42 +00:00
case ' v ' : /* verbose mode */
2016-11-13 01:14:57 +00:00
g_displayLevel + + ;
2018-03-21 14:14:13 +00:00
argument + + ;
2014-06-09 01:42:39 +00:00
break ;
2014-10-10 19:58:42 +00:00
case ' p ' : /* pause at the end */
2016-12-21 09:39:27 +00:00
use_pause = 1 ;
2018-03-21 14:14:13 +00:00
argument + + ;
2014-10-10 19:58:42 +00:00
break ;
2014-04-29 20:39:08 +00:00
case ' i ' :
argument + + ;
2015-04-10 22:42:17 +00:00
nbTests = 0 ; duration = 0 ;
2016-08-11 10:18:45 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-04-29 20:39:08 +00:00
nbTests * = 10 ;
2019-06-30 20:59:49 +00:00
nbTests + = ( unsigned ) ( * argument - ' 0 ' ) ;
2014-04-29 20:39:08 +00:00
argument + + ;
}
break ;
2014-10-10 19:58:42 +00:00
2015-04-10 22:42:17 +00:00
case ' T ' :
argument + + ;
nbTests = 0 ; duration = 0 ;
2016-08-11 10:18:45 +00:00
for ( ; ; ) {
2015-04-12 15:40:58 +00:00
switch ( * argument )
2015-04-10 22:42:17 +00:00
{
2015-04-12 15:40:58 +00:00
case ' m ' : duration * = 60 ; argument + + ; continue ;
case ' s ' :
case ' n ' : argument + + ; continue ;
case ' 0 ' :
case ' 1 ' :
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
2019-06-30 20:59:49 +00:00
case ' 9 ' : duration * = 10 ; duration + = ( U32 ) ( * argument + + - ' 0 ' ) ; continue ;
2015-04-10 22:42:17 +00:00
}
break ;
}
break ;
2014-04-29 20:39:08 +00:00
case ' s ' :
argument + + ;
seed = 0 ; seedset = 1 ;
2016-08-11 10:18:45 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-04-29 20:39:08 +00:00
seed * = 10 ;
2019-06-30 20:59:49 +00:00
seed + = ( U32 ) ( * argument - ' 0 ' ) ;
2014-04-29 20:39:08 +00:00
argument + + ;
}
break ;
2014-10-10 19:58:42 +00:00
case ' t ' : /* select starting test nb */
2014-05-19 23:40:29 +00:00
argument + + ;
2014-12-10 08:05:44 +00:00
testNb = 0 ;
2016-08-11 10:18:45 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-05-19 23:40:29 +00:00
testNb * = 10 ;
2019-06-30 20:59:49 +00:00
testNb + = ( unsigned ) ( * argument - ' 0 ' ) ;
2014-05-19 23:40:29 +00:00
argument + + ;
}
break ;
2014-10-10 19:58:42 +00:00
case ' P ' : /* change probability */
2014-04-29 22:44:49 +00:00
argument + + ;
proba = 0 ;
2016-08-11 10:18:45 +00:00
while ( ( * argument > = ' 0 ' ) & & ( * argument < = ' 9 ' ) ) {
2014-04-29 22:44:49 +00:00
proba * = 10 ;
proba + = * argument - ' 0 ' ;
argument + + ;
}
if ( proba < 0 ) proba = 0 ;
if ( proba > 100 ) proba = 100 ;
break ;
2014-04-29 20:39:08 +00:00
default : ;
}
}
}
}
2016-12-04 19:05:36 +00:00
printf ( " Starting LZ4 fuzzer (%i-bits, v%s) \n " , ( int ) ( sizeof ( size_t ) * 8 ) , LZ4_versionString ( ) ) ;
2014-04-29 20:39:08 +00:00
2016-09-03 02:48:24 +00:00
if ( ! seedset ) {
time_t const t = time ( NULL ) ;
U32 const h = XXH32 ( & t , sizeof ( t ) , 1 ) ;
seed = h % 10000 ;
}
2014-04-29 20:39:08 +00:00
printf ( " Seed = %u \n " , seed ) ;
2016-09-03 02:48:24 +00:00
2014-04-29 22:44:49 +00:00
if ( proba ! = FUZ_COMPRESSIBILITY_DEFAULT ) printf ( " Compressibility : %i%% \n " , proba ) ;
2014-04-29 20:39:08 +00:00
2016-12-28 16:47:10 +00:00
if ( ( seedset = = 0 ) & & ( testNb = = 0 ) ) { FUZ_unitTests ( LZ4HC_CLEVEL_DEFAULT ) ; FUZ_unitTests ( LZ4HC_CLEVEL_OPT_MIN ) ; }
2014-04-29 20:39:08 +00:00
2019-06-30 22:36:32 +00:00
nbTests + = ( nbTests = = 0 ) ; /* avoid zero */
2014-04-29 20:39:08 +00:00
2016-08-11 10:18:45 +00:00
{ int const result = FUZ_test ( seed , nbTests , testNb , ( ( double ) proba ) / 100 , duration ) ;
2016-12-21 09:39:27 +00:00
if ( use_pause ) {
2014-10-10 19:58:42 +00:00
DISPLAY ( " press enter ... \n " ) ;
2015-04-12 07:21:35 +00:00
( void ) getchar ( ) ;
2014-10-10 19:58:42 +00:00
}
return result ;
}
2014-04-29 20:39:08 +00:00
}