164 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
#include <stdio.h>
 | 
						|
#include <stddef.h>
 | 
						|
#include <stdint.h>
 | 
						|
#include <string.h>
 | 
						|
#include <assert.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <inttypes.h>
 | 
						|
#include "zlib.h"
 | 
						|
 | 
						|
#define CHECK_ERR(err, msg) { \
 | 
						|
    if (err != Z_OK) { \
 | 
						|
        fprintf(stderr, "%s error: %d\n", msg, err); \
 | 
						|
        exit(1); \
 | 
						|
    } \
 | 
						|
}
 | 
						|
 | 
						|
static const uint8_t *data;
 | 
						|
static size_t dataLen;
 | 
						|
static alloc_func zalloc = NULL;
 | 
						|
static free_func zfree = NULL;
 | 
						|
static size_t dictionaryLen = 0;
 | 
						|
static unsigned long dictId; /* Adler32 value of the dictionary */
 | 
						|
 | 
						|
/* ===========================================================================
 | 
						|
 * Test deflate() with preset dictionary
 | 
						|
 */
 | 
						|
void test_dict_deflate(unsigned char **compr, size_t *comprLen)
 | 
						|
{
 | 
						|
    z_stream c_stream; /* compression stream */
 | 
						|
    int err;
 | 
						|
    int level = data[0] % 11 - 1; /* [-1..9]
 | 
						|
      compression levels
 | 
						|
      #define Z_NO_COMPRESSION         0
 | 
						|
      #define Z_BEST_SPEED             1
 | 
						|
      #define Z_BEST_COMPRESSION       9
 | 
						|
      #define Z_DEFAULT_COMPRESSION  (-1) */
 | 
						|
 | 
						|
    int method = Z_DEFLATED; /* The deflate compression method (the only one
 | 
						|
                                supported in this version) */
 | 
						|
    int windowBits = 8 + data[0] % 8; /* The windowBits parameter is the base
 | 
						|
      two logarithm of the window size (the size of the history buffer).  It
 | 
						|
      should be in the range 8..15 for this version of the library. */
 | 
						|
    int memLevel = 1 + data[0] % 9;   /* memLevel=1 uses minimum memory but is
 | 
						|
      slow and reduces compression ratio; memLevel=9 uses maximum memory for
 | 
						|
      optimal speed. */
 | 
						|
    int strategy = data[0] % 5;       /* [0..4]
 | 
						|
      #define Z_FILTERED            1
 | 
						|
      #define Z_HUFFMAN_ONLY        2
 | 
						|
      #define Z_RLE                 3
 | 
						|
      #define Z_FIXED               4
 | 
						|
      #define Z_DEFAULT_STRATEGY    0 */
 | 
						|
 | 
						|
    /* deflate would fail for no-compression or for speed levels. */
 | 
						|
    if (level == 0 || level == 1)
 | 
						|
      level = -1;
 | 
						|
 | 
						|
    c_stream.zalloc = zalloc;
 | 
						|
    c_stream.zfree = zfree;
 | 
						|
    c_stream.opaque = (void *)0;
 | 
						|
 | 
						|
    err = deflateInit2(&c_stream, level, method, windowBits, memLevel, strategy);
 | 
						|
    CHECK_ERR(err, "deflateInit");
 | 
						|
 | 
						|
    err = deflateSetDictionary(
 | 
						|
        &c_stream, (const unsigned char *)data, dictionaryLen);
 | 
						|
    CHECK_ERR(err, "deflateSetDictionary");
 | 
						|
 | 
						|
    /* deflateBound does not provide enough space for low compression levels. */
 | 
						|
    *comprLen = 100 + 2 * deflateBound(&c_stream, dataLen);
 | 
						|
    *compr = (uint8_t *)calloc(1, *comprLen);
 | 
						|
 | 
						|
    dictId = c_stream.adler;
 | 
						|
    c_stream.next_out = *compr;
 | 
						|
    c_stream.avail_out = (unsigned int)(*comprLen);
 | 
						|
 | 
						|
    c_stream.next_in = (Bytef *)data;
 | 
						|
    c_stream.avail_in = dataLen;
 | 
						|
 | 
						|
    err = deflate(&c_stream, Z_FINISH);
 | 
						|
    if (err != Z_STREAM_END) {
 | 
						|
        fprintf(stderr, "deflate dict should report Z_STREAM_END\n");
 | 
						|
        exit(1);
 | 
						|
    }
 | 
						|
    err = deflateEnd(&c_stream);
 | 
						|
    CHECK_ERR(err, "deflateEnd");
 | 
						|
}
 | 
						|
 | 
						|
/* ===========================================================================
 | 
						|
 * Test inflate() with a preset dictionary
 | 
						|
 */
 | 
						|
void test_dict_inflate(unsigned char *compr, size_t comprLen) {
 | 
						|
  int err;
 | 
						|
  z_stream d_stream; /* decompression stream */
 | 
						|
  unsigned char *uncompr;
 | 
						|
 | 
						|
  d_stream.zalloc = zalloc;
 | 
						|
  d_stream.zfree = zfree;
 | 
						|
  d_stream.opaque = (void *)0;
 | 
						|
 | 
						|
  d_stream.next_in = compr;
 | 
						|
  d_stream.avail_in = (unsigned int)comprLen;
 | 
						|
 | 
						|
  err = inflateInit(&d_stream);
 | 
						|
  CHECK_ERR(err, "inflateInit");
 | 
						|
 | 
						|
  uncompr = (uint8_t *)calloc(1, dataLen);
 | 
						|
  d_stream.next_out = uncompr;
 | 
						|
  d_stream.avail_out = (unsigned int)dataLen;
 | 
						|
 | 
						|
  for (;;) {
 | 
						|
    err = inflate(&d_stream, Z_NO_FLUSH);
 | 
						|
    if (err == Z_STREAM_END)
 | 
						|
      break;
 | 
						|
    if (err == Z_NEED_DICT) {
 | 
						|
      if (d_stream.adler != dictId) {
 | 
						|
        fprintf(stderr, "unexpected dictionary");
 | 
						|
        exit(1);
 | 
						|
      }
 | 
						|
      err = inflateSetDictionary(
 | 
						|
          &d_stream, (const unsigned char *)data, dictionaryLen);
 | 
						|
    }
 | 
						|
    CHECK_ERR(err, "inflate with dict");
 | 
						|
  }
 | 
						|
 | 
						|
  err = inflateEnd(&d_stream);
 | 
						|
  CHECK_ERR(err, "inflateEnd");
 | 
						|
 | 
						|
  if (memcmp(uncompr, data, dataLen)) {
 | 
						|
    fprintf(stderr, "bad inflate with dict\n");
 | 
						|
    exit(1);
 | 
						|
  }
 | 
						|
 | 
						|
  free(uncompr);
 | 
						|
}
 | 
						|
 | 
						|
int LLVMFuzzerTestOneInput(const uint8_t *d, size_t size) {
 | 
						|
  size_t comprLen = 0;
 | 
						|
  uint8_t *compr;
 | 
						|
 | 
						|
  /* Discard inputs larger than 100Kb. */
 | 
						|
  static size_t kMaxSize = 100 * 1024;
 | 
						|
 | 
						|
  if (size < 1 || size > kMaxSize)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  data = d;
 | 
						|
  dataLen = size;
 | 
						|
 | 
						|
  /* Set up the contents of the dictionary.  The size of the dictionary is
 | 
						|
     intentionally selected to be of unusual size.  To help cover more corner
 | 
						|
     cases, the size of the dictionary is read from the input data.  */
 | 
						|
  dictionaryLen = data[0];
 | 
						|
  if (dictionaryLen > dataLen)
 | 
						|
    dictionaryLen = dataLen;
 | 
						|
 | 
						|
  test_dict_deflate(&compr, &comprLen);
 | 
						|
  test_dict_inflate(compr, comprLen);
 | 
						|
 | 
						|
  free(compr);
 | 
						|
 | 
						|
  /* This function must return 0. */
 | 
						|
  return 0;
 | 
						|
}
 |