/src/speex/contrib/oss-fuzz/speexenc_fuzzer.cc
Line | Count | Source |
1 | | /* Copyright (C) 2024 Tristan Matthews |
2 | | File: speexenc_fuzzer.cc |
3 | | |
4 | | Redistribution and use in source and binary forms, with or without |
5 | | modification, are permitted provided that the following conditions |
6 | | are met: |
7 | | |
8 | | - Redistributions of source code must retain the above copyright |
9 | | notice, this list of conditions and the following disclaimer. |
10 | | |
11 | | - Redistributions in binary form must reproduce the above copyright |
12 | | notice, this list of conditions and the following disclaimer in the |
13 | | documentation and/or other materials provided with the distribution. |
14 | | |
15 | | - Neither the name of the Xiph.org Foundation nor the names of its |
16 | | contributors may be used to endorse or promote products derived from |
17 | | this software without specific prior written permission. |
18 | | |
19 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
23 | | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
24 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
25 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
26 | | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
27 | | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
28 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
29 | | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | | */ |
31 | | |
32 | | #include <fuzzer/FuzzedDataProvider.h> |
33 | | #include <stdint.h> |
34 | | #include <stdlib.h> |
35 | | #include <string.h> |
36 | | |
37 | | #include "speex/speex.h" |
38 | | #include "speex/speex_stereo.h" |
39 | | |
40 | 26.2k | #define MAX_PACKET (1500) |
41 | 22.6k | #define SAMPLES (32000 * 10) |
42 | 22.6k | #define MAX_FRAME_SAMP (2000) |
43 | 26.2k | #define MAX_FRAME_BYTES (2000) |
44 | | |
45 | | static const int sampling_rates[] = {8000, 16000, 32000}; |
46 | | static const int channels[] = {1, 2}; |
47 | | static const int modes[] = {SPEEX_MODEID_NB, SPEEX_MODEID_WB, SPEEX_MODEID_UWB}; |
48 | | |
49 | | static spx_int16_t inbuf[sizeof(spx_int16_t) * SAMPLES] = {0}; |
50 | | static unsigned char packet[MAX_PACKET + 257]; |
51 | | |
52 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
53 | 3.65k | { |
54 | 3.65k | FuzzedDataProvider fdp(data, size); |
55 | | |
56 | 3.65k | int num_channels = fdp.PickValueInArray(channels); |
57 | 3.65k | spx_int32_t sampling_rate = fdp.PickValueInArray(sampling_rates); |
58 | 3.65k | spx_int32_t modeID = fdp.PickValueInArray(modes); |
59 | 3.65k | spx_int32_t quality = fdp.ConsumeIntegralInRange(0, 10); |
60 | 3.65k | spx_int32_t complexity = fdp.ConsumeIntegralInRange(0, 10); |
61 | 3.65k | spx_int32_t vbr_max = fdp.ConsumeIntegralInRange(1, 20000); |
62 | 3.65k | spx_int32_t bitrate = fdp.ConsumeIntegralInRange(1, 20000); |
63 | | |
64 | | /* speex_encoder_ctl expects spx_int32_t, not bools */ |
65 | 3.65k | spx_int32_t vbr_enabled = fdp.ConsumeBool(); |
66 | 3.65k | spx_int32_t vad_enabled = fdp.ConsumeBool(); |
67 | 3.65k | spx_int32_t abr_enabled = fdp.ConsumeBool(); |
68 | 3.65k | spx_int32_t dtx_enabled = fdp.ConsumeBool(); |
69 | 3.65k | spx_int32_t highpass_enabled = fdp.ConsumeBool(); |
70 | | |
71 | 3.65k | spx_int32_t lookahead = 0; |
72 | 3.65k | float vbr_quality = quality; |
73 | | |
74 | 3.65k | const SpeexMode *mode; |
75 | 3.65k | spx_int32_t frame_size; |
76 | 3.65k | int nb_encoded = 0; |
77 | 3.65k | SpeexBits bits; |
78 | 3.65k | char cbits[MAX_FRAME_BYTES]; |
79 | 3.65k | void *st; |
80 | 3.65k | mode = speex_lib_get_mode(modeID); |
81 | | |
82 | 3.65k | st = speex_encoder_init(mode); |
83 | 3.65k | speex_bits_init(&bits); |
84 | | |
85 | 3.65k | speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size); |
86 | 3.65k | speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity); |
87 | 3.65k | speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &sampling_rate); |
88 | | |
89 | 3.65k | if (quality >= 0) |
90 | 3.65k | { |
91 | 3.65k | if (vbr_enabled) |
92 | 1.65k | { |
93 | 1.65k | if (vbr_max > 0) |
94 | 1.65k | speex_encoder_ctl(st, SPEEX_SET_VBR_MAX_BITRATE, &vbr_max); |
95 | 1.65k | speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_quality); |
96 | 1.65k | } |
97 | 2.00k | else |
98 | 2.00k | speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality); |
99 | 3.65k | } |
100 | 3.65k | if (bitrate) |
101 | 3.65k | speex_encoder_ctl(st, SPEEX_SET_BITRATE, &bitrate); |
102 | | |
103 | 3.65k | if (vbr_enabled) |
104 | 1.65k | { |
105 | 1.65k | int tmp = 1; |
106 | 1.65k | speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp); |
107 | 1.65k | } |
108 | | |
109 | 3.65k | if (vad_enabled) |
110 | 1.75k | { |
111 | 1.75k | int tmp = 1; |
112 | 1.75k | speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp); |
113 | 1.75k | } |
114 | | |
115 | 3.65k | if (dtx_enabled) |
116 | 1.72k | { |
117 | 1.72k | int tmp = 1; |
118 | 1.72k | speex_encoder_ctl(st, SPEEX_SET_DTX, &tmp); |
119 | 1.72k | } |
120 | | |
121 | 3.65k | if (abr_enabled) |
122 | 1.13k | speex_encoder_ctl(st, SPEEX_SET_ABR, &abr_enabled); |
123 | | |
124 | 3.65k | speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &highpass_enabled); |
125 | | |
126 | 3.65k | speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); |
127 | | |
128 | 3.65k | fdp.ConsumeData(inbuf, sizeof(inbuf)); |
129 | | |
130 | 3.65k | size_t samp_count = 0; |
131 | 26.2k | do { |
132 | 26.2k | const int frame_size_samples = frame_size * sampling_rate / 2000; |
133 | | |
134 | 26.2k | if (num_channels == 2) |
135 | 4.77k | speex_encode_stereo_int(&inbuf[samp_count * num_channels], frame_size, &bits); |
136 | | |
137 | 26.2k | speex_encode_int(st, &inbuf[samp_count * num_channels], &bits); |
138 | | |
139 | 26.2k | speex_bits_insert_terminator(&bits); |
140 | 26.2k | size_t byte_to_write = speex_bits_nbytes(&bits); |
141 | 26.2k | size_t bytes_written = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES); |
142 | 26.2k | speex_bits_reset(&bits); |
143 | | |
144 | 26.2k | nb_encoded += frame_size; |
145 | 26.2k | if (nb_encoded < 0 || nb_encoded > MAX_PACKET) { |
146 | 3.65k | break; |
147 | 3.65k | } |
148 | 22.6k | samp_count += frame_size; |
149 | 22.6k | } while (samp_count < ((SAMPLES / 2) - MAX_FRAME_SAMP)); |
150 | | |
151 | 3.65k | speex_bits_destroy(&bits); |
152 | 3.65k | speex_encoder_destroy(st); |
153 | | |
154 | 3.65k | return 0; |
155 | 3.65k | } |