Skip to content

Commit

Permalink
fuzz: more complete fuzzing
Browse files Browse the repository at this point in the history
  • Loading branch information
catenacyber committed Oct 3, 2023
1 parent 53947c1 commit dc96f48
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 13 deletions.
42 changes: 29 additions & 13 deletions c/fuzz/decode_fuzzer.c
Expand Up @@ -8,19 +8,34 @@

#include <brotli/decode.h>

#define kBufferSize 1024

// Entry point for LibFuzzer.
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
size_t addend = 0;
if (size > 0)
addend = data[size - 1] & 7;
const uint8_t* next_in = data;

const int kBufferSize = 1024;
uint8_t* buffer = (uint8_t*) malloc(kBufferSize);
if (!buffer) {
// OOM is out-of-scope here.
if (size < 3) {
return 0;
}
size_t addend = data[0] & 7;
uint32_t decode_large = (data[0] & 8) ? 1 : 0;
BrotliSharedDictionaryType dict_type = (data[0] & 0x10) ? BROTLI_SHARED_DICTIONARY_SERIALIZED : BROTLI_SHARED_DICTIONARY_RAW;
size--;
data++;
uint16_t dict_size = (uint16_t)((((uint16_t)data[0]) << 8)) | ((uint16_t) data[1]);
const uint8_t* dict = data;
size-=2;
data+=2;
if (size < dict_size) {
dict_size = 0;
}
size-=dict_size;
data+=dict_size;

if (addend == 0)
addend = size;

const uint8_t* next_in = data;

uint8_t buffer[kBufferSize];
/* The biggest "magic number" in brotli is 16MiB - 16, so no need to check
the cases with much longer output. */
const size_t total_out_limit = (addend == 0) ? (1 << 26) : (1 << 24);
Expand All @@ -29,12 +44,14 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
BrotliDecoderState* state = BrotliDecoderCreateInstance(0, 0, 0);
if (!state) {
// OOM is out-of-scope here.
free(buffer);
return 0;
}

if (addend == 0)
addend = size;
BrotliDecoderSetParameter(state, BROTLI_DECODER_PARAM_LARGE_WINDOW, decode_large);
if (dict_size > 0) {
BrotliDecoderAttachDictionary(state, BROTLI_SHARED_DICTIONARY_RAW,
dict_size, dict);
}
/* Test both fast (addend == size) and slow (addend <= 7) decoding paths. */
for (size_t i = 0; i < size;) {
size_t next_i = i + addend;
Expand All @@ -58,6 +75,5 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
}

BrotliDecoderDestroyInstance(state);
free(buffer);
return 0;
}
100 changes: 100 additions & 0 deletions c/fuzz/encode_fuzzer.c
@@ -0,0 +1,100 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

#include <brotli/encode.h>

#define kBufferSize 1024

// Entry point for LibFuzzer.
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 6) {
return 0;
}
size_t addend = data[0] & 7;
BrotliSharedDictionaryType dict_type = (data[0] & 8) ? BROTLI_SHARED_DICTIONARY_SERIALIZED : BROTLI_SHARED_DICTIONARY_RAW;
int dict_quality = data[0] >> 4;
data++;
size--;
uint32_t enc_mode = data[0] & 3;
uint32_t enc_quality = (data[0] >> 2) & 0xF;
uint32_t enc_disable = (data[0] & 0x40) ? 1 : 0;
uint32_t enc_large = (data[0] & 0x80) ? 1 : 0;
data++;
size--;
uint32_t enc_lgwin = BROTLI_MIN_WINDOW_BITS + (data[0] & 0xF);
uint32_t enc_lgblock = BROTLI_MIN_INPUT_BLOCK_BITS + (data[0] >> 4);
data++;
size--;
uint32_t enc_npostfix = (data[0] & 0x7);
uint32_t enc_ndirect = (data[0] >> 4) << enc_npostfix;
data++;
size--;
uint16_t dict_size = (uint16_t)((((uint16_t)data[0]) << 8)) | ((uint16_t) data[1]);
const uint8_t* dict_data = data;
size-=2;
data+=2;
if (size < dict_size) {
dict_size = 0;
}
size-=dict_size;
data+=dict_size;

const uint8_t* next_in = data;
if (addend == 0)
addend = size;

uint8_t buffer[kBufferSize];
/* The biggest "magic number" in brotli is 16MiB - 16, so no need to check
the cases with much longer output. */
const size_t total_out_limit = (addend == 0) ? (1 << 26) : (1 << 24);
size_t total_out = 0;
BrotliEncoderPreparedDictionary *dict = NULL;
if (dict_size > 0) {
dict = BrotliEncoderPrepareDictionary(dict_type, dict_size, dict_data, dict_quality, NULL, NULL, NULL);
}
BrotliEncoderState* state = BrotliEncoderCreateInstance(0, 0, 0);
if (dict) {
BrotliEncoderAttachPreparedDictionary(state, dict);
}
BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE, enc_mode);
BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, enc_quality);
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, enc_lgwin);
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK, enc_lgblock);
BrotliEncoderSetParameter(state, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, enc_disable);
BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW, enc_large);
BrotliEncoderSetParameter(state, BROTLI_PARAM_NPOSTFIX, enc_npostfix);
BrotliEncoderSetParameter(state, BROTLI_PARAM_NDIRECT, enc_ndirect);

/* Test both fast (addend == size) and slow (addend <= 7) decoding paths. */
for (size_t i = 0; i < size;) {
size_t next_i = i + addend;
if (next_i > size)
next_i = size;
size_t avail_in = next_i - i;
i = next_i;
size_t avail_out = kBufferSize;
uint8_t* next_out = buffer;
while (avail_out > 0 && avail_in > 0) {
if (!BrotliEncoderCompressStream(state, (next_i == size) ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
&avail_in, &next_in, &avail_out, &next_out, &total_out)) {
break;
}
if (avail_out == 0) {
avail_out = kBufferSize;
next_out = buffer;
}
}
}
// TODO check round-trip compression

if (dict) {
BrotliEncoderDestroyPreparedDictionary(dict);
}
BrotliEncoderDestroyInstance(state);
return 0;
}

0 comments on commit dc96f48

Please sign in to comment.