xref: /aosp_15_r20/external/libopus/tests/opus_decode_fuzzer.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
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