1 #include <cstddef>
2 #include <cstdint>
3 #include <limits>
4 
5 #include <fuzzing/datasource/datasource.hpp>
6 #include <fuzzing/memory.hpp>
7 
8 #include "FLAC++/encoder.h"
9 
10 #define SAMPLE_VALUE_LIMIT (1024*1024*10)
11 
12 static_assert(SAMPLE_VALUE_LIMIT <= std::numeric_limits<FLAC__int32>::max(), "Invalid SAMPLE_VALUE_LIMIT");
13 static_assert(-SAMPLE_VALUE_LIMIT >= std::numeric_limits<FLAC__int32>::min(), "Invalid SAMPLE_VALUE_LIMIT");
14 
15 namespace FLAC {
16 	namespace Encoder {
17         class FuzzerStream : public Stream {
18             private:
19                 // fuzzing::datasource::Datasource& ds;
20             public:
FuzzerStream(fuzzing::datasource::Datasource &)21                 FuzzerStream(fuzzing::datasource::Datasource&) :
22                     Stream() { }
23 
write_callback(const FLAC__byte buffer[],size_t bytes,uint32_t,uint32_t)24                 ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, uint32_t /* samples */, uint32_t /* current_frame */) override {
25                     fuzzing::memory::memory_test(buffer, bytes);
26 #if 0
27                     try {
28                         if ( ds.Get<bool>() == true ) {
29 	                        return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
30                         }
31                     } catch ( ... ) { }
32 #endif
33                     return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
34                 }
35         };
36     }
37 }
38 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)39 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
40     fuzzing::datasource::Datasource ds(data, size);
41     FLAC::Encoder::FuzzerStream encoder(ds);
42 
43     const int channels = 2;
44 	encoder.set_channels(channels);
45 	encoder.set_bits_per_sample(16);
46 
47     try {
48         ::FLAC__StreamEncoderInitStatus ret;
49 
50         if ( ds.Get<bool>() ) {
51             ret = encoder.init();
52         } else {
53             ret = encoder.init_ogg();
54         }
55 
56         if ( ret != FLAC__STREAM_ENCODER_INIT_STATUS_OK ) {
57             goto end;
58         }
59 
60         {
61             const bool res = encoder.set_streamable_subset(ds.Get<bool>());
62             fuzzing::memory::memory_test(res);
63         }
64         {
65             const bool res = encoder.set_ogg_serial_number(ds.Get<long>());
66             fuzzing::memory::memory_test(res);
67         }
68         {
69             const bool res = encoder.set_verify(ds.Get<bool>());
70             fuzzing::memory::memory_test(res);
71         }
72         {
73             const bool res = encoder.set_compression_level(ds.Get<uint8_t>());
74             fuzzing::memory::memory_test(res);
75         }
76         {
77             const bool res = encoder.set_do_exhaustive_model_search(ds.Get<bool>());
78             fuzzing::memory::memory_test(res);
79         }
80         {
81             const bool res = encoder.set_do_mid_side_stereo(ds.Get<bool>());
82             fuzzing::memory::memory_test(res);
83         }
84         {
85             const bool res = encoder.set_loose_mid_side_stereo(ds.Get<bool>());
86             fuzzing::memory::memory_test(res);
87         }
88         {
89             const auto s = ds.Get<std::string>();
90             const bool res = encoder.set_apodization(s.data());
91             fuzzing::memory::memory_test(res);
92         }
93         {
94             const bool res = encoder.set_max_lpc_order(ds.Get<uint8_t>());
95             fuzzing::memory::memory_test(res);
96         }
97         {
98             const bool res = encoder.set_qlp_coeff_precision(ds.Get<uint32_t>());
99             fuzzing::memory::memory_test(res);
100         }
101         {
102             const bool res = encoder.set_do_qlp_coeff_prec_search(ds.Get<bool>());
103             fuzzing::memory::memory_test(res);
104         }
105         {
106             const bool res = encoder.set_do_escape_coding(ds.Get<bool>());
107             fuzzing::memory::memory_test(res);
108         }
109         {
110             const bool res = encoder.set_min_residual_partition_order(ds.Get<uint32_t>());
111             fuzzing::memory::memory_test(res);
112         }
113         {
114             const bool res = encoder.set_max_residual_partition_order(ds.Get<uint32_t>());
115             fuzzing::memory::memory_test(res);
116         }
117         {
118             const bool res = encoder.set_rice_parameter_search_dist(ds.Get<uint32_t>());
119             fuzzing::memory::memory_test(res);
120         }
121         {
122             const bool res = encoder.set_total_samples_estimate(ds.Get<uint64_t>());
123             fuzzing::memory::memory_test(res);
124         }
125 
126         while ( ds.Get<bool>() ) {
127             {
128                 auto dat = ds.GetVector<FLAC__int32>();
129                 for (size_t i = 0; i < dat.size(); i++) {
130                     if ( SAMPLE_VALUE_LIMIT != 0 ) {
131                         if ( dat[i] < -SAMPLE_VALUE_LIMIT ) {
132                             dat[i] = -SAMPLE_VALUE_LIMIT;
133                         } else if ( dat[i] > SAMPLE_VALUE_LIMIT ) {
134                             dat[i] = SAMPLE_VALUE_LIMIT;
135                         }
136                     }
137                 }
138                 const uint32_t samples = dat.size() / 2;
139                 if ( samples > 0 ) {
140                     const int32_t* ptr = dat.data();
141                     const bool res = encoder.process_interleaved(ptr, samples);
142                     fuzzing::memory::memory_test(res);
143                 }
144             }
145         }
146     } catch ( ... ) { }
147 
148 end:
149     {
150         const bool res = encoder.finish();
151         fuzzing::memory::memory_test(res);
152     }
153     return 0;
154 }
155