1 #include <fuzzer/FuzzedDataProvider.h>
2
3 #include <cstddef>
4 #include <cstdint>
5 #include <cstdio>
6 #include <cstdlib>
7 #include <vector>
8
9 #include "mpg123.h"
10
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)11 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
12 static bool initialized = false;
13 if (!initialized) {
14 mpg123_init();
15 initialized = true;
16 }
17 int ret;
18 mpg123_handle* handle = mpg123_new(nullptr, &ret);
19 if (handle == nullptr) {
20 return 0;
21 }
22
23 ret = mpg123_param(handle, MPG123_ADD_FLAGS, MPG123_QUIET, 0.);
24 if(ret == MPG123_OK)
25 ret = mpg123_open_feed(handle);
26 if (ret != MPG123_OK) {
27 mpg123_delete(handle);
28 return 0;
29 }
30
31 std::vector<uint8_t> output_buffer(mpg123_outblock(handle));
32
33 size_t output_written = 0;
34 // Initially, start by feeding the decoder more data.
35 int decode_ret = MPG123_NEED_MORE;
36 FuzzedDataProvider provider(data, size);
37 while ((decode_ret != MPG123_ERR)) {
38 if (decode_ret == MPG123_NEED_MORE) {
39 if (provider.remaining_bytes() == 0
40 || mpg123_tellframe(handle) > 10000
41 || mpg123_tell_stream(handle) > 1<<20) {
42 break;
43 }
44 const size_t next_size = provider.ConsumeIntegralInRange<size_t>(
45 0,
46 provider.remaining_bytes());
47 auto next_input = provider.ConsumeBytes<unsigned char>(next_size);
48 decode_ret = mpg123_decode(handle, next_input.data(), next_input.size(),
49 output_buffer.data(), output_buffer.size(),
50 &output_written);
51 } else if (decode_ret != MPG123_ERR && decode_ret != MPG123_NEED_MORE) {
52 decode_ret = mpg123_decode(handle, nullptr, 0, output_buffer.data(),
53 output_buffer.size(), &output_written);
54 } else {
55 // Unhandled mpg123_decode return value.
56 abort();
57 }
58 }
59
60 mpg123_delete(handle);
61
62 return 0;
63 }
64