seek.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /* fuzzer_seek
  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_decoder.h"
  34. #include "common.h"
  35. int write_abort_check_counter = -1;
  36. #if 0 /* set to 1 to debug */
  37. #define FPRINTF_DEBUG_ONLY(...) fprintf(__VA_ARGS__)
  38. #else
  39. #define FPRINTF_DEBUG_ONLY(...)
  40. #endif
  41. #define CONFIG_LENGTH 2
  42. static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
  43. {
  44. (void)decoder, (void)frame, (void)buffer, (void)client_data;
  45. if(write_abort_check_counter > 0) {
  46. write_abort_check_counter--;
  47. if(write_abort_check_counter == 0)
  48. return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
  49. } else if(write_abort_check_counter == 0)
  50. /* This must not happen: write callback called after abort is returned */
  51. abort();
  52. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  53. }
  54. static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus error, void *client_data)
  55. {
  56. (void)decoder, (void)error, (void)client_data;
  57. }
  58. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
  59. {
  60. FLAC__bool decoder_valid = true;
  61. FLAC__StreamDecoder *decoder;
  62. uint8_t command_length;
  63. FLAC__bool init_bools[16], ogg;
  64. if(size > 2 && data[1] < 128) /* Use MSB as on/off */
  65. alloc_check_threshold = data[1];
  66. else
  67. alloc_check_threshold = INT32_MAX;
  68. alloc_check_counter = 0;
  69. write_abort_check_counter = -1;
  70. /* allocate the decoder */
  71. if((decoder = FLAC__stream_decoder_new()) == NULL) {
  72. fprintf(stderr, "ERROR: allocating decoder\n");
  73. return 1;
  74. }
  75. /* Use first byte for configuration, leave at least one byte of input */
  76. if(size < 1 + CONFIG_LENGTH){
  77. FLAC__stream_decoder_delete(decoder);
  78. return 0;
  79. }
  80. /* First 4 bits for configuration bools, next 4 for length of command section */
  81. for(int i = 0; i < 4; i++)
  82. init_bools[i] = data[i/8] & (1 << (i % 8));
  83. command_length = data[0] >> 4;
  84. /* Leave at least one byte as input */
  85. if(command_length >= size - 1 - CONFIG_LENGTH)
  86. command_length = size - 1 - CONFIG_LENGTH;
  87. /* Dump decoder input to file */
  88. {
  89. FILE * file_to_decode = fopen("/tmp/tmp.flac","w");
  90. fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_decode);
  91. fclose(file_to_decode);
  92. }
  93. ogg = init_bools[0];
  94. FLAC__stream_decoder_set_md5_checking(decoder,init_bools[1]);
  95. if(init_bools[2])
  96. FLAC__stream_decoder_set_metadata_respond_all(decoder);
  97. if(init_bools[3])
  98. FLAC__stream_decoder_set_metadata_ignore_all(decoder);
  99. /* initialize decoder */
  100. if(decoder_valid) {
  101. FLAC__StreamDecoderInitStatus init_status;
  102. if(ogg)
  103. init_status = FLAC__stream_decoder_init_ogg_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
  104. else
  105. init_status = FLAC__stream_decoder_init_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
  106. if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
  107. decoder_valid = false;
  108. }
  109. }
  110. /* Run commands */
  111. for(uint8_t i = 0; decoder_valid && (i < command_length); i++){
  112. const uint8_t * command = data+CONFIG_LENGTH+i;
  113. uint8_t shift = 1u << (command[0] >> 3);
  114. FLAC__uint64 seekpos;
  115. switch(command[0] & 15){
  116. case 0:
  117. FPRINTF_DEBUG_ONLY(stderr,"end_of_stream\n");
  118. decoder_valid = FLAC__stream_decoder_process_until_end_of_stream(decoder);
  119. break;
  120. case 1:
  121. FPRINTF_DEBUG_ONLY(stderr,"end_of_metadata\n");
  122. decoder_valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder);
  123. break;
  124. case 2:
  125. FPRINTF_DEBUG_ONLY(stderr,"single\n");
  126. decoder_valid = FLAC__stream_decoder_process_single(decoder);
  127. break;
  128. case 3:
  129. FPRINTF_DEBUG_ONLY(stderr,"skip_single\n");
  130. decoder_valid = FLAC__stream_decoder_skip_single_frame(decoder);
  131. break;
  132. case 4:
  133. FPRINTF_DEBUG_ONLY(stderr,"reset\n");
  134. decoder_valid = FLAC__stream_decoder_reset(decoder);
  135. break;
  136. case 5:
  137. FPRINTF_DEBUG_ONLY(stderr,"flush\n");
  138. decoder_valid = FLAC__stream_decoder_flush(decoder);
  139. break;
  140. case 6:
  141. case 14:
  142. shift = 1u << (command[0] >> 3);
  143. FPRINTF_DEBUG_ONLY(stderr,"seek short %hhu\n",shift);
  144. decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,shift);
  145. break;
  146. case 7:
  147. if(i+8 >= command_length) /* Not enough data available to do this */
  148. break;
  149. seekpos = ((FLAC__uint64)command[1] << 56) +
  150. ((FLAC__uint64)command[2] << 48) +
  151. ((FLAC__uint64)command[3] << 40) +
  152. ((FLAC__uint64)command[4] << 32) +
  153. ((FLAC__uint64)command[5] << 24) +
  154. ((FLAC__uint64)command[6] << 16) +
  155. ((FLAC__uint64)command[7] << 8) +
  156. command[8];
  157. i+=8;
  158. FPRINTF_DEBUG_ONLY(stderr,"seek long %lu\n",seekpos);
  159. decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,seekpos);
  160. break;
  161. case 8:
  162. /* Set abort on write callback */
  163. write_abort_check_counter = (command[0] >> 4) + 1;
  164. break;
  165. }
  166. }
  167. FLAC__stream_decoder_finish(decoder);
  168. FLAC__stream_decoder_delete(decoder);
  169. return 0;
  170. }