1*a58d3d2aSXin Li /* Copyright (c) 2017 Google Inc. */
2*a58d3d2aSXin Li /*
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li
7*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright
8*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer.
9*a58d3d2aSXin Li
10*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
11*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
12*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
13*a58d3d2aSXin Li
14*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*a58d3d2aSXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*a58d3d2aSXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17*a58d3d2aSXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
18*a58d3d2aSXin Li OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*a58d3d2aSXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*a58d3d2aSXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21*a58d3d2aSXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22*a58d3d2aSXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23*a58d3d2aSXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*a58d3d2aSXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a58d3d2aSXin Li */
26*a58d3d2aSXin Li
27*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
28*a58d3d2aSXin Li #include "config.h"
29*a58d3d2aSXin Li #endif
30*a58d3d2aSXin Li
31*a58d3d2aSXin Li #include <stdint.h>
32*a58d3d2aSXin Li #include <stdlib.h>
33*a58d3d2aSXin Li #include <string.h>
34*a58d3d2aSXin Li #include "opus.h"
35*a58d3d2aSXin Li #include "opus_types.h"
36*a58d3d2aSXin Li
37*a58d3d2aSXin Li #define MAX_FRAME_SAMP 5760
38*a58d3d2aSXin Li #define MAX_PACKET 1500
39*a58d3d2aSXin Li
40*a58d3d2aSXin Li /* 4 bytes: packet length, 4 bytes: encoder final range */
41*a58d3d2aSXin Li #define SETUP_BYTE_COUNT 8
42*a58d3d2aSXin Li
43*a58d3d2aSXin Li #define MAX_DECODES 12
44*a58d3d2aSXin Li
45*a58d3d2aSXin Li typedef struct {
46*a58d3d2aSXin Li int fs;
47*a58d3d2aSXin Li int channels;
48*a58d3d2aSXin Li } TocInfo;
49*a58d3d2aSXin Li
ParseToc(const uint8_t * toc,TocInfo * const info)50*a58d3d2aSXin Li static void ParseToc(const uint8_t *toc, TocInfo *const info) {
51*a58d3d2aSXin Li const int samp_freqs[5] = {8000, 12000, 16000, 24000, 48000};
52*a58d3d2aSXin Li const int bandwidth = opus_packet_get_bandwidth(toc);
53*a58d3d2aSXin Li
54*a58d3d2aSXin Li info->fs = samp_freqs[bandwidth - OPUS_BANDWIDTH_NARROWBAND];
55*a58d3d2aSXin Li info->channels = opus_packet_get_nb_channels(toc);
56*a58d3d2aSXin Li }
57*a58d3d2aSXin Li
58*a58d3d2aSXin Li /* Treats the input data as concatenated packets encoded by opus_demo,
59*a58d3d2aSXin Li * structured as
60*a58d3d2aSXin Li * bytes 0..3: packet length
61*a58d3d2aSXin Li * bytes 4..7: encoder final range
62*a58d3d2aSXin Li * bytes 8+ : Opus packet, including ToC
63*a58d3d2aSXin Li */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)64*a58d3d2aSXin Li int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
65*a58d3d2aSXin Li OpusDecoder *dec;
66*a58d3d2aSXin Li opus_int16 *pcm;
67*a58d3d2aSXin Li uint8_t *temp_data;
68*a58d3d2aSXin Li TocInfo toc;
69*a58d3d2aSXin Li int i = 0;
70*a58d3d2aSXin Li int err = OPUS_OK;
71*a58d3d2aSXin Li int num_decodes = 0;
72*a58d3d2aSXin Li
73*a58d3d2aSXin Li /* Not enough data to setup the decoder (+1 for the ToC) */
74*a58d3d2aSXin Li if (size < SETUP_BYTE_COUNT + 1) {
75*a58d3d2aSXin Li return 0;
76*a58d3d2aSXin Li }
77*a58d3d2aSXin Li
78*a58d3d2aSXin Li /* Create decoder based on info from the first ToC available */
79*a58d3d2aSXin Li ParseToc(&data[SETUP_BYTE_COUNT], &toc);
80*a58d3d2aSXin Li
81*a58d3d2aSXin Li dec = opus_decoder_create(toc.fs, toc.channels, &err);
82*a58d3d2aSXin Li if (err != OPUS_OK || dec == NULL) {
83*a58d3d2aSXin Li return 0;
84*a58d3d2aSXin Li }
85*a58d3d2aSXin Li
86*a58d3d2aSXin Li pcm = (opus_int16*) malloc(sizeof(*pcm) * MAX_FRAME_SAMP * toc.channels);
87*a58d3d2aSXin Li
88*a58d3d2aSXin Li while (i + SETUP_BYTE_COUNT < size && num_decodes++ < MAX_DECODES) {
89*a58d3d2aSXin Li int len, fec;
90*a58d3d2aSXin Li
91*a58d3d2aSXin Li len = (opus_uint32) data[i ] << 24 |
92*a58d3d2aSXin Li (opus_uint32) data[i + 1] << 16 |
93*a58d3d2aSXin Li (opus_uint32) data[i + 2] << 8 |
94*a58d3d2aSXin Li (opus_uint32) data[i + 3];
95*a58d3d2aSXin Li if (len > MAX_PACKET || len < 0 || i + SETUP_BYTE_COUNT + len > size) {
96*a58d3d2aSXin Li break;
97*a58d3d2aSXin Li }
98*a58d3d2aSXin Li
99*a58d3d2aSXin Li /* Bytes 4..7 represent encoder final range, but are unused here.
100*a58d3d2aSXin Li * Instead, byte 4 is repurposed to determine if FEC is used. */
101*a58d3d2aSXin Li fec = data[i + 4] & 1;
102*a58d3d2aSXin Li
103*a58d3d2aSXin Li if (len == 0) {
104*a58d3d2aSXin Li /* Lost packet */
105*a58d3d2aSXin Li int frame_size;
106*a58d3d2aSXin Li opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&frame_size));
107*a58d3d2aSXin Li (void) opus_decode(dec, NULL, len, pcm, frame_size, fec);
108*a58d3d2aSXin Li } else {
109*a58d3d2aSXin Li temp_data = (uint8_t*) malloc(len);
110*a58d3d2aSXin Li memcpy(temp_data, &data[i + SETUP_BYTE_COUNT], len);
111*a58d3d2aSXin Li
112*a58d3d2aSXin Li (void) opus_decode(dec, temp_data, len, pcm, MAX_FRAME_SAMP, fec);
113*a58d3d2aSXin Li
114*a58d3d2aSXin Li free(temp_data);
115*a58d3d2aSXin Li }
116*a58d3d2aSXin Li
117*a58d3d2aSXin Li i += SETUP_BYTE_COUNT + len;
118*a58d3d2aSXin Li }
119*a58d3d2aSXin Li
120*a58d3d2aSXin Li opus_decoder_destroy(dec);
121*a58d3d2aSXin Li free(pcm);
122*a58d3d2aSXin Li
123*a58d3d2aSXin Li return 0;
124*a58d3d2aSXin Li }
125