Index: third_party/opus/src/tests/opus_decode_fuzzer.c |
diff --git a/third_party/opus/src/tests/opus_decode_fuzzer.c b/third_party/opus/src/tests/opus_decode_fuzzer.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4b4a3f37f464b43c5c2e86cdcfc005fa18973e0b |
--- /dev/null |
+++ b/third_party/opus/src/tests/opus_decode_fuzzer.c |
@@ -0,0 +1,125 @@ |
+/* Copyright (c) 2017 Google Inc. */ |
+/* |
+ Redistribution and use in source and binary forms, with or without |
+ modification, are permitted provided that the following conditions |
+ are met: |
+ |
+ - Redistributions of source code must retain the above copyright |
+ notice, this list of conditions and the following disclaimer. |
+ |
+ - Redistributions in binary form must reproduce the above copyright |
+ notice, this list of conditions and the following disclaimer in the |
+ documentation and/or other materials provided with the distribution. |
+ |
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+*/ |
+ |
+#ifdef HAVE_CONFIG_H |
+#include "config.h" |
+#endif |
+ |
+#include <stdlib.h> |
+#include <string.h> |
+#include "opus.h" |
+#include "opus_types.h" |
+ |
+#define MAX_FRAME_SAMP 5760 |
+#define MAX_PACKET 1500 |
+ |
+/* 4 bytes: packet length, 4 bytes: encoder final range */ |
+#define SETUP_BYTE_COUNT 8 |
+ |
+typedef struct { |
+ int fs; |
+ int channels; |
+} TocInfo; |
+ |
+static void ParseToc(const uint8_t *toc, TocInfo *const info) { |
+ const int samp_freqs[5] = {8000, 12000, 16000, 24000, 48000}; |
+ const int bandwidth = opus_packet_get_bandwidth(toc); |
+ |
+ info->fs = samp_freqs[bandwidth - OPUS_BANDWIDTH_NARROWBAND]; |
+ info->channels = opus_packet_get_nb_channels(toc); |
+} |
+ |
+/* Treats the input data as concatenated packets encoded by opus_demo, |
+ * structured as |
+ * bytes 0..3: packet length |
+ * bytes 4..7: encoder final range |
+ * bytes 8+ : Opus packet, including ToC |
+ */ |
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
+ OpusDecoder *dec; |
+ opus_int16 *pcm; |
+ uint8_t *packet; |
+ TocInfo toc; |
+ int i, err; |
+ |
+ /* Not enough data to setup the decoder (+1 for the ToC) */ |
+ if (size < SETUP_BYTE_COUNT + 1) { |
+ return 0; |
+ } |
+ |
+ /* Create decoder based on info from the first ToC available */ |
+ ParseToc(&data[SETUP_BYTE_COUNT], &toc); |
+ |
+ dec = opus_decoder_create(toc.fs, toc.channels, &err); |
+ if (err != OPUS_OK | dec == NULL) { |
+ return 0; |
+ } |
+ |
+ pcm = (opus_int16*) malloc(sizeof(*pcm) * MAX_FRAME_SAMP * toc.channels); |
+ packet = (uint8_t*) calloc(MAX_PACKET, sizeof(*packet)); |
+ |
+ i = 0; |
+ while (1) { |
+ int len, fec; |
+ |
+ if (i + SETUP_BYTE_COUNT >= size) { |
+ break; |
+ } |
+ |
+ len = (opus_uint32) data[i ] << 24 | |
+ (opus_uint32) data[i + 1] << 16 | |
+ (opus_uint32) data[i + 2] << 8 | |
+ (opus_uint32) data[i + 3]; |
+ if (len > MAX_PACKET || len < 0) { |
+ break; |
+ } |
+ |
+ /* Bytes 4..7 represent encoder final range, but are unused here. |
+ * Instead, byte 4 is repurposed to determine if FEC is used. */ |
+ fec = data[i + 4] & 1; |
+ |
+ /* Lost packet */ |
+ if (len == 0) { |
+ int frame_size; |
+ opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&frame_size)); |
+ (void) opus_decode(dec, NULL, size, pcm, frame_size, fec); |
+ } else { |
+ if (i + SETUP_BYTE_COUNT + len > size) { |
+ break; |
+ } |
+ memcpy(pcm, &data[i + SETUP_BYTE_COUNT], len); |
+ (void) opus_decode(dec, data, size, pcm, MAX_FRAME_SAMP, fec); |
+ } |
+ |
+ i += SETUP_BYTE_COUNT + len; |
+ } |
+ |
+ opus_decoder_destroy(dec); |
+ free(pcm); |
+ free(packet); |
+ |
+ return 0; |
+} |