aboutsummaryrefslogtreecommitdiff
path: root/projects/opus
diff options
context:
space:
mode:
authorRavi Jotwani <rjotwani@google.com>2020-07-14 16:49:49 -0700
committerGitHub <noreply@github.com>2020-07-14 16:49:49 -0700
commit80fa75131ed387ce1bb729e6aedd0be83ddaa52b (patch)
treef877c8066c3dee510ec49b83acf3da2675cd4d44 /projects/opus
parent96c3d4f440d9880dfb7c9aa9d6fe49959ff6124d (diff)
downloadoss-fuzz-80fa75131ed387ce1bb729e6aedd0be83ddaa52b.tar.gz
[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
Diffstat (limited to 'projects/opus')
-rw-r--r--projects/opus/Dockerfile1
-rw-r--r--projects/opus/build.sh5
-rw-r--r--projects/opus/opus_multi_fuzzer.c99
3 files changed, 103 insertions, 2 deletions
diff --git a/projects/opus/Dockerfile b/projects/opus/Dockerfile
index ccdd01937..717b88270 100644
--- a/projects/opus/Dockerfile
+++ b/projects/opus/Dockerfile
@@ -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/
diff --git a/projects/opus/build.sh b/projects/opus/build.sh
index 0cd91bf76..850007151 100644
--- a/projects/opus/build.sh
+++ b/projects/opus/build.sh
@@ -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
diff --git a/projects/opus/opus_multi_fuzzer.c b/projects/opus/opus_multi_fuzzer.c
new file mode 100644
index 000000000..de63bfb3e
--- /dev/null
+++ b/projects/opus/opus_multi_fuzzer.c
@@ -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;
+}