• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <stddef.h>
16 #include <stdlib.h>
17 
18 #include "opus.h"
19 #include "opus_multistream.h"
20 
21 struct TocInfo {
22   opus_int32 frequency;  // in [Hz*1000]
23   int channels;          // number of channels; either 1 or 2
24   int frame_len_x2;      // in [ms*2]. x2 is to avoid float value of 2.5 ms
25 };
26 
extractTocInfo(const uint8_t toc,struct TocInfo * const info)27 void extractTocInfo(const uint8_t toc, struct TocInfo *const info) {
28   const int frame_lengths_x2[3][4] = {
29     {20, 40, 80, 120},
30     {20, 40, 20, 40},
31     {5, 10, 20, 40}
32   };
33 
34   info->channels = toc & 4 ? 2 : 1;
35 
36   const uint8_t config = toc >> 3;
37 
38   int len_index;
39   if (config < 12) {
40     len_index = 0;
41   } else if (config < 16) {
42     len_index = 1;
43   } else {
44     len_index = 2;
45   }
46   info->frame_len_x2 = frame_lengths_x2[len_index][config & 3];
47 
48   switch (config >> 2) {
49     case 0: info->frequency = 8; break;
50     case 1: info->frequency = 12; break;
51     case 2: info->frequency = 16; break;
52     case 3: info->frequency = (config < 14) ? 24 : 48; break;
53     case 4: info->frequency = 8; break;
54     case 5: info->frequency = 16; break;
55     case 6: info->frequency = 24; break;
56     default: info->frequency = 48; break;
57   }
58 }
59 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)60 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
61   if (size < 3 || size > 1000000) return 0;
62 
63   // Using last byte as a number of streams (instead of rand_r). Each stream
64   // should be at least 3 bytes long hence divmod.
65   int streams = 1 + data[size - 1] % (size / 3);
66   if (streams > 255) streams = 255;
67   unsigned char *mapping = (unsigned char*) malloc(sizeof(unsigned char)*streams);
68   if (!mapping) return 0;
69 
70   for (int i = 0; i < streams; ++i) {
71     mapping[i] = i;
72   }
73 
74   struct TocInfo info;
75   extractTocInfo(*data, &info);
76 
77   int error = 0;
78   OpusMSDecoder *const decoder = opus_multistream_decoder_create(
79       info.frequency * 1000, streams, streams, 0, mapping, &error);
80 
81   if (!decoder || error) return 0;
82 
83   const int frame_size = (info.frequency * info.frame_len_x2) / 2;
84   opus_int16 *pcm = (opus_int16*) malloc(sizeof(opus_int16)*frame_size*streams);
85   if (!pcm) goto exit;
86 
87   // opus_decode wants us to use its return value, but we don't really care.
88   const int foo =
89       opus_multistream_decode(decoder, data, size, pcm, frame_size, 0);
90   (void)foo;
91 
92   opus_multistream_decoder_destroy(decoder);
93 
94   free(pcm);
95 
96 exit:
97   free(mapping);
98   return 0;
99 }
100