Skip to content

Commit 19d3b57

Browse files
committed
fuzz: more complete fuzzing
1 parent ed1995b commit 19d3b57

File tree

2 files changed

+129
-12
lines changed

2 files changed

+129
-12
lines changed

c/fuzz/decode_fuzzer.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,45 @@
88

99
#include <brotli/decode.h>
1010

11+
#define kBufferSize 1024
12+
1113
// Entry point for LibFuzzer.
1214
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
13-
size_t addend = 0;
14-
if (size > 0)
15-
addend = data[size - 1] & 7;
16-
const uint8_t* next_in = data;
17-
18-
const int kBufferSize = 1024;
19-
uint8_t* buffer = (uint8_t*) malloc(kBufferSize);
20-
if (!buffer) {
21-
// OOM is out-of-scope here.
15+
if (size < 3) {
2216
return 0;
2317
}
18+
size_t addend = data[0] & 7;
19+
uint32_t decode_large = (data[0] & 8) ? 1 : 0;
20+
BrotliSharedDictionaryType dict_type = (data[0] & 0x10) ? BROTLI_SHARED_DICTIONARY_SERIALIZED : BROTLI_SHARED_DICTIONARY_RAW;
21+
size--;
22+
data++;
23+
uint16_t dict_size = (uint16_t)((((uint16_t)data[0]) << 8)) | ((uint16_t) data[1]);
24+
const uint8_t* dict = data;
25+
size-=2;
26+
data+=2;
27+
if (size < dict_size) {
28+
dict_size = 0;
29+
}
30+
size-=dict_size;
31+
data+=dict_size;
32+
33+
if (addend == 0)
34+
addend = size;
35+
36+
const uint8_t* next_in = data;
37+
38+
uint8_t buffer[kBufferSize];
2439
/* The biggest "magic number" in brotli is 16MiB - 16, so no need to check
2540
the cases with much longer output. */
2641
const size_t total_out_limit = (addend == 0) ? (1 << 26) : (1 << 24);
2742
size_t total_out = 0;
2843

2944
BrotliDecoderState* state = BrotliDecoderCreateInstance(0, 0, 0);
30-
31-
if (addend == 0)
32-
addend = size;
45+
BrotliDecoderSetParameter(state, BROTLI_DECODER_PARAM_LARGE_WINDOW, decode_large);
46+
if (dict_size > 0) {
47+
BrotliDecoderAttachDictionary(state, BROTLI_SHARED_DICTIONARY_RAW,
48+
dict_size, dict);
49+
}
3350
/* Test both fast (addend == size) and slow (addend <= 7) decoding paths. */
3451
for (size_t i = 0; i < size;) {
3552
size_t next_i = i + addend;

c/fuzz/encode_fuzzer.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright 2015 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include <stddef.h>
6+
#include <stdint.h>
7+
#include <stdlib.h>
8+
9+
#include <brotli/encode.h>
10+
11+
#define kBufferSize 1024
12+
13+
// Entry point for LibFuzzer.
14+
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
15+
if (size < 6) {
16+
return 0;
17+
}
18+
size_t addend = data[0] & 7;
19+
BrotliSharedDictionaryType dict_type = (data[0] & 8) ? BROTLI_SHARED_DICTIONARY_SERIALIZED : BROTLI_SHARED_DICTIONARY_RAW;
20+
int dict_quality = data[0] >> 4;
21+
data++;
22+
size--;
23+
uint32_t enc_mode = data[0] & 3;
24+
uint32_t enc_quality = (data[0] >> 2) & 0xF;
25+
uint32_t enc_disable = (data[0] & 0x40) ? 1 : 0;
26+
uint32_t enc_large = (data[0] & 0x80) ? 1 : 0;
27+
data++;
28+
size--;
29+
uint32_t enc_lgwin = BROTLI_MIN_WINDOW_BITS + (data[0] & 0xF);
30+
uint32_t enc_lgblock = BROTLI_MIN_INPUT_BLOCK_BITS + (data[0] >> 4);
31+
data++;
32+
size--;
33+
uint32_t enc_npostfix = (data[0] & 0x7);
34+
uint32_t enc_ndirect = (data[0] >> 4) << enc_npostfix;
35+
data++;
36+
size--;
37+
uint16_t dict_size = (uint16_t)((((uint16_t)data[0]) << 8)) | ((uint16_t) data[1]);
38+
const uint8_t* dict_data = data;
39+
size-=2;
40+
data+=2;
41+
if (size < dict_size) {
42+
dict_size = 0;
43+
}
44+
size-=dict_size;
45+
data+=dict_size;
46+
47+
const uint8_t* next_in = data;
48+
if (addend == 0)
49+
addend = size;
50+
51+
uint8_t buffer[kBufferSize];
52+
/* The biggest "magic number" in brotli is 16MiB - 16, so no need to check
53+
the cases with much longer output. */
54+
const size_t total_out_limit = (addend == 0) ? (1 << 26) : (1 << 24);
55+
size_t total_out = 0;
56+
BrotliEncoderPreparedDictionary *dict = NULL;
57+
if (dict_size > 0) {
58+
dict = BrotliEncoderPrepareDictionary(dict_type, dict_size, dict_data, dict_quality, NULL, NULL, NULL);
59+
}
60+
BrotliEncoderState* state = BrotliEncoderCreateInstance(0, 0, 0);
61+
if (dict) {
62+
BrotliEncoderAttachPreparedDictionary(state, dict);
63+
}
64+
BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE, enc_mode);
65+
BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, enc_quality);
66+
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, enc_lgwin);
67+
BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK, enc_lgblock);
68+
BrotliEncoderSetParameter(state, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, enc_disable);
69+
BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW, enc_large);
70+
BrotliEncoderSetParameter(state, BROTLI_PARAM_NPOSTFIX, enc_npostfix);
71+
BrotliEncoderSetParameter(state, BROTLI_PARAM_NDIRECT, enc_ndirect);
72+
73+
/* Test both fast (addend == size) and slow (addend <= 7) decoding paths. */
74+
for (size_t i = 0; i < size;) {
75+
size_t next_i = i + addend;
76+
if (next_i > size)
77+
next_i = size;
78+
size_t avail_in = next_i - i;
79+
i = next_i;
80+
size_t avail_out = kBufferSize;
81+
uint8_t* next_out = buffer;
82+
while (avail_out > 0 && avail_in > 0) {
83+
if (!BrotliEncoderCompressStream(state, (next_i == size) ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
84+
&avail_in, &next_in, &avail_out, &next_out, &total_out)) {
85+
break;
86+
}
87+
if (avail_out == 0) {
88+
avail_out = kBufferSize;
89+
next_out = buffer;
90+
}
91+
}
92+
}
93+
// TODO check round-trip compression
94+
95+
if (dict) {
96+
BrotliEncoderDestroyPreparedDictionary(dict);
97+
}
98+
BrotliEncoderDestroyInstance(state);
99+
return 0;
100+
}

0 commit comments

Comments
 (0)