mirror of https://github.com/google/oss-fuzz.git
[opus] Add new fuzzer (#4118)
* added new opus fuzzer, build working * added missing license header, cleaned up Dockerfile * fixed build process * changed build process depending on C or C++ fuzzer * converted opus_multi_fuzzer from C++ to C, reverted build script to only accept C files
This commit is contained in:
parent
96c3d4f440
commit
80fa75131e
|
@ -21,3 +21,4 @@ RUN git clone https://gitlab.xiph.org/xiph/opus.git
|
|||
RUN wget https://opus-codec.org/static/testvectors/opus_testvectors.tar.gz
|
||||
WORKDIR opus
|
||||
COPY build.sh $SRC/
|
||||
COPY *.c tests/
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
##############################################################################
|
||||
set -eu
|
||||
|
||||
FUZZERS="opus_decode_fuzzer"
|
||||
FUZZERS="opus_decode_fuzzer opus_multi_fuzzer"
|
||||
BUILDS=(floating fixed)
|
||||
|
||||
tar xvf $SRC/opus_testvectors.tar.gz
|
||||
|
@ -53,7 +53,8 @@ for build in "${BUILDS[@]}"; do
|
|||
|
||||
# Setup the .options and test corpus zip files using the corresponding
|
||||
# fuzzer's name
|
||||
cp tests/$fuzzer.options $OUT/${fuzzer}_${build}.options
|
||||
[ -f tests/$fuzzer.options ] \
|
||||
&& cp tests/$fuzzer.options $OUT/${fuzzer}_${build}.options
|
||||
zip -r $OUT/${fuzzer}_${build}_seed_corpus.zip opus_testvectors/
|
||||
done
|
||||
done
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "opus.h"
|
||||
#include "opus_multistream.h"
|
||||
|
||||
struct TocInfo {
|
||||
opus_int32 frequency; // in [Hz*1000]
|
||||
int channels; // number of channels; either 1 or 2
|
||||
int frame_len_x2; // in [ms*2]. x2 is to avoid float value of 2.5 ms
|
||||
};
|
||||
|
||||
void extractTocInfo(const uint8_t toc, struct TocInfo *const info) {
|
||||
const int frame_lengths_x2[3][4] = {
|
||||
{20, 40, 80, 120},
|
||||
{20, 40, 20, 40},
|
||||
{5, 10, 20, 40}
|
||||
};
|
||||
|
||||
info->channels = toc & 4 ? 2 : 1;
|
||||
|
||||
const uint8_t config = toc >> 3;
|
||||
|
||||
int len_index;
|
||||
if (config < 12) {
|
||||
len_index = 0;
|
||||
} else if (config < 16) {
|
||||
len_index = 1;
|
||||
} else {
|
||||
len_index = 2;
|
||||
}
|
||||
info->frame_len_x2 = frame_lengths_x2[len_index][config & 3];
|
||||
|
||||
switch (config >> 2) {
|
||||
case 0: info->frequency = 8; break;
|
||||
case 1: info->frequency = 12; break;
|
||||
case 2: info->frequency = 16; break;
|
||||
case 3: info->frequency = (config < 14) ? 24 : 48; break;
|
||||
case 4: info->frequency = 8; break;
|
||||
case 5: info->frequency = 16; break;
|
||||
case 6: info->frequency = 24; break;
|
||||
default: info->frequency = 48; break;
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < 3 || size > 1000000) return 0;
|
||||
|
||||
// Using last byte as a number of streams (instead of rand_r). Each stream
|
||||
// should be at least 3 bytes long hence divmod.
|
||||
int streams = 1 + data[size - 1] % (size / 3);
|
||||
if (streams > 255) streams = 255;
|
||||
unsigned char *mapping = (unsigned char*) malloc(sizeof(unsigned char)*streams);
|
||||
if (!mapping) return 0;
|
||||
|
||||
for (int i = 0; i < streams; ++i) {
|
||||
mapping[i] = i;
|
||||
}
|
||||
|
||||
struct TocInfo info;
|
||||
extractTocInfo(*data, &info);
|
||||
|
||||
int error = 0;
|
||||
OpusMSDecoder *const decoder = opus_multistream_decoder_create(
|
||||
info.frequency * 1000, streams, streams, 0, mapping, &error);
|
||||
|
||||
if (!decoder || error) return 0;
|
||||
|
||||
const int frame_size = (info.frequency * info.frame_len_x2) / 2;
|
||||
opus_int16 *pcm = (opus_int16*) malloc(sizeof(opus_int16)*frame_size*streams);
|
||||
if (!pcm) goto exit;
|
||||
|
||||
// opus_decode wants us to use its return value, but we don't really care.
|
||||
const int foo =
|
||||
opus_multistream_decode(decoder, data, size, pcm, frame_size, 0);
|
||||
(void)foo;
|
||||
|
||||
opus_multistream_decoder_destroy(decoder);
|
||||
|
||||
free(pcm);
|
||||
|
||||
exit:
|
||||
free(mapping);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue