encoder_v2.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /* fuzzer_encoder_v2
  2. * Copyright (C) 2022-2023 Xiph.Org Foundation
  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. #include <cstdlib>
  32. #include <cstring> /* for memcpy */
  33. #include "FLAC/stream_encoder.h"
  34. #include "FLAC/metadata.h"
  35. extern "C" {
  36. #include "share/private.h"
  37. }
  38. #include "common.h"
  39. /* This C++ fuzzer uses the FLAC and not FLAC++ because the latter lacks a few
  40. * hidden functions like FLAC__stream_encoder_disable_constant_subframes. It
  41. * is still processed by a C++ compiler because that's what oss-fuzz expects */
  42. static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data)
  43. {
  44. (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
  45. return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
  46. }
  47. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
  48. {
  49. FLAC__bool encoder_valid = true;
  50. FLAC__StreamEncoder *encoder = 0;
  51. FLAC__StreamEncoderState state;
  52. FLAC__StreamMetadata *metadata[16] = {NULL};
  53. unsigned num_metadata = 0;
  54. FLAC__StreamMetadata_VorbisComment_Entry VorbisCommentField;
  55. unsigned sample_rate, channels, bps;
  56. uint64_t samples_estimate, samples_in_input;
  57. unsigned compression_level, input_data_width, blocksize, max_lpc_order, qlp_coeff_precision, min_residual_partition_order, max_residual_partition_order, metadata_mask, instruction_set_disable_mask;
  58. FLAC__bool ogg, write_to_file, interleaved;
  59. FLAC__bool data_bools[24];
  60. /* Set alloc threshold. This check was added later and no spare config
  61. * bytes were left, so we're reusing the sample rate as that of little
  62. * consequence to the encoder and decoder except reading the frame header */
  63. if(size < 3)
  64. return 0;
  65. alloc_check_threshold = data[2];
  66. alloc_check_counter = 0;
  67. /* allocate the encoder */
  68. if((encoder = FLAC__stream_encoder_new()) == NULL) {
  69. fprintf(stderr, "ERROR: allocating encoder\n");
  70. return 1;
  71. }
  72. /* Use first 20 byte for configuration */
  73. if(size < 20){
  74. FLAC__stream_encoder_delete(encoder);
  75. return 0;
  76. }
  77. /* First 3 byte for sample rate, 4th byte for channels, 5th byte for bps */
  78. sample_rate = ((unsigned)data[0] << 16) + ((unsigned)data[1] << 8) + data[2];
  79. channels = data[3];
  80. bps = data[4];
  81. /* Number of samples estimate, format accepts 36-bit max */
  82. samples_estimate = ((uint64_t)data[5] << 32) + ((unsigned)data[6] << 24) + ((unsigned)data[7] << 16) + ((unsigned)data[8] << 8) + data[9];
  83. compression_level = data[10]&0b1111;
  84. input_data_width = 1 + (data[10]>>4)%4;
  85. samples_in_input = (size-20)/input_data_width;
  86. blocksize = ((unsigned)data[11] << 8) + (unsigned)data[12];
  87. max_lpc_order = data[13];
  88. qlp_coeff_precision = data[14];
  89. min_residual_partition_order = data[15] & 0b1111;
  90. max_residual_partition_order = data[15] & 0b11110000;
  91. metadata_mask = data[16];
  92. instruction_set_disable_mask = data[17];
  93. /* Get array of bools from configuration */
  94. for(int i = 0; i < 16; i++)
  95. data_bools[i] = data[18+i/8] & (1 << (i % 8));
  96. ogg = data_bools[0];
  97. interleaved = data_bools[1];
  98. write_to_file = data_bools[13];
  99. /* Set input and process parameters */
  100. encoder_valid &= FLAC__stream_encoder_set_verify(encoder, data_bools[2]);
  101. encoder_valid &= FLAC__stream_encoder_set_channels(encoder, channels);
  102. encoder_valid &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
  103. encoder_valid &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
  104. encoder_valid &= FLAC__stream_encoder_set_total_samples_estimate(encoder, samples_estimate);
  105. encoder_valid &= FLAC__stream_encoder_disable_instruction_set(encoder, instruction_set_disable_mask);
  106. encoder_valid &= FLAC__stream_encoder_set_limit_min_bitrate(encoder, data_bools[15]);
  107. /* Set compression related parameters */
  108. encoder_valid &= FLAC__stream_encoder_set_compression_level(encoder, compression_level);
  109. if(data_bools[3]){
  110. /* Bias towards regular compression levels */
  111. encoder_valid &= FLAC__stream_encoder_set_blocksize(encoder, blocksize);
  112. encoder_valid &= FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
  113. encoder_valid &= FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
  114. encoder_valid &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
  115. /* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
  116. * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
  117. * options makes the fuzzer slower, most options do not expose new code when combined.
  118. * Therefore, combining slow options is disabled for large inputs. Any input containing
  119. * more than 65536 * 2 samples (max blocksize, stereo) is considered large
  120. */
  121. if(samples_in_input < (2*65536)) {
  122. encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, data_bools[4]);
  123. encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, data_bools[5]);
  124. encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, data_bools[6]);
  125. encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, data_bools[7]);
  126. /* Combining model search, precision search and a high residual partition order is especially
  127. * expensive, so limit that even further. This high partition order can only be set on
  128. * large blocksize and with streamable subset disabled */
  129. if(samples_in_input < (2 * 4609) || data_bools[4] || !data_bools[7] || !data_bools[5] || max_residual_partition_order < 9 || blocksize < 4609)
  130. encoder_valid &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
  131. }
  132. else {
  133. if(!data_bools[4])
  134. encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, false);
  135. else if(data_bools[6])
  136. encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, true);
  137. else if(data_bools[7])
  138. encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, true);
  139. else if(data_bools[5])
  140. encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, true);
  141. }
  142. encoder_valid &= FLAC__stream_encoder_set_do_mid_side_stereo(encoder, data_bools[8]);
  143. encoder_valid &= FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, data_bools[9]);
  144. encoder_valid &= FLAC__stream_encoder_disable_constant_subframes(encoder, data_bools[10]);
  145. encoder_valid &= FLAC__stream_encoder_disable_fixed_subframes(encoder, data_bools[11]);
  146. encoder_valid &= FLAC__stream_encoder_disable_verbatim_subframes(encoder, data_bools[12]);
  147. }
  148. /* Disable alloc check if requested */
  149. if(encoder_valid && data_bools[14])
  150. alloc_check_threshold = INT32_MAX;
  151. /* add metadata */
  152. if(encoder_valid && (metadata_mask & 1)) {
  153. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO)) == NULL)
  154. encoder_valid = false;
  155. else
  156. num_metadata++;
  157. }
  158. if(encoder_valid && (metadata_mask & 2) && size > 21){
  159. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL)
  160. encoder_valid = false;
  161. else {
  162. metadata[num_metadata++]->length = (((unsigned)data[20]) << 8) + (unsigned)(data[21]);
  163. }
  164. }
  165. if(encoder_valid && (metadata_mask & 4) && size > 20){
  166. FLAC__byte * application_data = (FLAC__byte *)malloc(size-20);
  167. if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL))
  168. encoder_valid = false;
  169. else {
  170. memcpy(application_data,data+20,size-20);
  171. FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0);
  172. }
  173. }
  174. if(encoder_valid && (metadata_mask & 8) && size > 25){
  175. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL)
  176. encoder_valid = false;
  177. else {
  178. unsigned seekpoint_spacing = ((unsigned)data[22] << 8) + data[23];
  179. unsigned total_samples_for_seekpoints = ((unsigned)data[24] << 8) + data[25];
  180. FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(metadata[num_metadata++], seekpoint_spacing, total_samples_for_seekpoints);
  181. }
  182. }
  183. if(encoder_valid && (metadata_mask & 16)){
  184. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL) {
  185. bool vorbiscomment_valid = true;
  186. /* Append a vorbis comment */
  187. if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Nothing to 🤔 report"))
  188. vorbiscomment_valid = false;
  189. else {
  190. if(FLAC__metadata_object_vorbiscomment_append_comment(metadata[num_metadata], VorbisCommentField, false)) {
  191. /* Insert a vorbis comment at the first index */
  192. if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Still nothing to report 🤔🤣"))
  193. vorbiscomment_valid = false;
  194. else
  195. if(!FLAC__metadata_object_vorbiscomment_insert_comment(metadata[num_metadata], 0, VorbisCommentField, false)) {
  196. free(VorbisCommentField.entry);
  197. vorbiscomment_valid = false;
  198. }
  199. }
  200. else {
  201. free(VorbisCommentField.entry);
  202. vorbiscomment_valid = false;
  203. }
  204. }
  205. if(!vorbiscomment_valid) {
  206. FLAC__metadata_object_delete(metadata[num_metadata]);
  207. metadata[num_metadata] = 0;
  208. }
  209. else
  210. num_metadata++;
  211. }
  212. }
  213. if(encoder_valid && (metadata_mask & 32)){
  214. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)) != NULL) {
  215. if(!FLAC__metadata_object_cuesheet_insert_blank_track(metadata[num_metadata],0)) {
  216. FLAC__metadata_object_delete(metadata[num_metadata]);
  217. metadata[num_metadata] = 0;
  218. }
  219. else {
  220. if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(metadata[num_metadata],0,0)) {
  221. FLAC__metadata_object_delete(metadata[num_metadata]);
  222. metadata[num_metadata] = 0;
  223. }
  224. else {
  225. metadata[num_metadata]->data.cue_sheet.tracks[0].number = 1;
  226. num_metadata++;
  227. }
  228. }
  229. }
  230. }
  231. if(encoder_valid && (metadata_mask & 64)){
  232. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)) != NULL) {
  233. num_metadata++;
  234. }
  235. }
  236. if(encoder_valid && (metadata_mask & 128)){
  237. if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_UNDEFINED)) != NULL) {
  238. metadata[num_metadata]->length = 24;
  239. metadata[num_metadata]->data.unknown.data = (FLAC__byte *)calloc(24, 1);
  240. num_metadata++;
  241. }
  242. }
  243. if(num_metadata && encoder_valid)
  244. encoder_valid = FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
  245. /* initialize encoder */
  246. if(encoder_valid) {
  247. FLAC__StreamEncoderInitStatus init_status;
  248. if(ogg)
  249. if(write_to_file)
  250. init_status = FLAC__stream_encoder_init_ogg_file(encoder, "/tmp/tmp.flac", NULL, NULL);
  251. else
  252. init_status = FLAC__stream_encoder_init_ogg_stream(encoder, NULL, write_callback, NULL, NULL, NULL, NULL);
  253. else
  254. if(write_to_file)
  255. init_status = FLAC__stream_encoder_init_file(encoder, "/tmp/tmp.flac", NULL, NULL);
  256. else
  257. init_status = FLAC__stream_encoder_init_stream(encoder, write_callback, NULL, NULL, NULL, NULL);
  258. if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
  259. encoder_valid = false;
  260. }
  261. }
  262. /* send samples to encoder */
  263. if(encoder_valid && size > (input_data_width*channels+26)) {
  264. unsigned samples = (size - 26)/input_data_width/channels;
  265. const uint8_t * pcm_data = data + 26;
  266. int32_t * data_as_int32 = (int32_t *)malloc(4*samples*channels);
  267. if(0 != data_as_int32){
  268. for(unsigned i = 0; i < samples*channels; i++)
  269. if(input_data_width == 1)
  270. data_as_int32[i] = (int32_t)pcm_data[i] - 0x80;
  271. else if(input_data_width == 2)
  272. data_as_int32[i] = (((int32_t)pcm_data[i*2] << 8) + pcm_data[i*2+1]) - 0x8000;
  273. else if(input_data_width == 3)
  274. data_as_int32[i] = (((int32_t)pcm_data[i*3] << 16) + ((int32_t)pcm_data[i*3+1] << 8) + pcm_data[i*3+2]) - 0x800000;
  275. else if(input_data_width == 4)
  276. data_as_int32[i] = (((int64_t)pcm_data[i*4] << 24) + ((int32_t)pcm_data[i*4+1] << 16) + ((int32_t)pcm_data[i*4+2] << 8) + pcm_data[i*4+3]) - 0x80000000;
  277. /* feed samples to encoder */
  278. if(interleaved)
  279. encoder_valid = FLAC__stream_encoder_process_interleaved(encoder, data_as_int32, samples);
  280. else {
  281. encoder_valid = FLAC__stream_encoder_process(encoder, (const int32_t*[]){data_as_int32,
  282. data_as_int32+samples,
  283. data_as_int32+samples*2,
  284. data_as_int32+samples*3,
  285. data_as_int32+samples*4, data_as_int32+samples*5, data_as_int32+samples*6, data_as_int32+samples*7}, samples);
  286. }
  287. free(data_as_int32);
  288. }
  289. else {
  290. encoder_valid = false;
  291. }
  292. }
  293. state = FLAC__stream_encoder_get_state(encoder);
  294. if(!(state == FLAC__STREAM_ENCODER_OK ||
  295. state == FLAC__STREAM_ENCODER_UNINITIALIZED ||
  296. state == FLAC__STREAM_ENCODER_CLIENT_ERROR ||
  297. ((state == FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR ||
  298. state == FLAC__STREAM_ENCODER_FRAMING_ERROR ||
  299. (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR &&
  300. FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR)) &&
  301. alloc_check_threshold < INT32_MAX))) {
  302. fprintf(stderr,"-----\nERROR: stream encoder returned %s\n-----\n",FLAC__stream_encoder_get_resolved_state_string(encoder));
  303. if(state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
  304. uint32_t frame_number, channel, sample_number;
  305. FLAC__int32 expected, got;
  306. FLAC__stream_encoder_get_verify_decoder_error_stats(encoder, NULL, &frame_number, &channel, &sample_number, &expected, &got);
  307. fprintf(stderr,"Frame number %d\nChannel %d\n Sample number %d\nExpected value %d\nGot %d\n", frame_number, channel, sample_number, expected, got);
  308. }
  309. abort();
  310. }
  311. FLAC__stream_encoder_finish(encoder);
  312. /* now that encoding is finished, the metadata can be freed */
  313. for(unsigned i = 0; i < 16; i++)
  314. if(0 != metadata[i])
  315. FLAC__metadata_object_delete(metadata[i]);
  316. FLAC__stream_encoder_delete(encoder);
  317. return 0;
  318. }