1 /****************************************************************************** 2 * 3 * Copyright 2022 Google LLC 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #include <lc3_cpp.h> 20 #include <fuzzer/FuzzedDataProvider.h> 21 22 using namespace lc3; 23 24 template <typename T> 25 T ConsumeInRange(FuzzedDataProvider &fdp, T min, T max) { 26 return fdp.ConsumeIntegralInRange<T>(min, max); 27 } 28 29 template <> 30 float ConsumeInRange(FuzzedDataProvider &fdp, float min, float max) { 31 return fdp.ConsumeFloatingPointInRange<float>(min, max); 32 } 33 34 template <typename T> 35 int encode(Encoder &e, int nchannels, int frame_size, FuzzedDataProvider &fdp, 36 T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max()) 37 { 38 int pcm_samples = nchannels * e.GetFrameSamples(); 39 if (fdp.remaining_bytes() < pcm_samples * sizeof(T)) 40 return -1; 41 42 std::vector<T> pcm(pcm_samples); 43 for (auto &s: pcm) 44 s = ConsumeInRange<T>(fdp, min, max); 45 46 e.Encode(pcm.data(), 47 frame_size, std::vector<uint8_t>(nchannels * frame_size).data()); 48 49 return 0; 50 } 51 52 int encode(Encoder &e, int frame_size, int nchannels, 53 PcmFormat fmt, FuzzedDataProvider &fdp) 54 { 55 int sample_bytes = 56 fmt == PcmFormat::kS16 ? sizeof(int16_t) : 57 fmt == PcmFormat::kS24 ? sizeof(int32_t) : 58 fmt == PcmFormat::kS24In3Le ? sizeof(uint8_t) * 3 : 59 fmt == PcmFormat::kF32 ? sizeof(float) : 0; 60 61 int pcm_bytes = nchannels * e.GetFrameSamples() * sample_bytes; 62 if (fdp.remaining_bytes() < pcm_bytes) 63 return -1; 64 65 e.Encode(fmt, fdp.ConsumeBytes<uint8_t>(pcm_bytes).data(), 66 frame_size, std::vector<uint8_t>(nchannels * frame_size).data()); 67 68 return 0; 69 } 70 71 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 72 { 73 const int dt_list[] = { 2500, 5000, 7500, 10000 }; 74 const int sr_list[] = { 8000, 16000, 24000, 32000, 48000 }; 75 76 FuzzedDataProvider fdp(data, size); 77 78 int dt_us = fdp.PickValueInArray(dt_list); 79 int sr_hz = fdp.PickValueInArray(sr_list); 80 int nchannels = fdp.PickValueInArray({1, 2}); 81 bool hrmode = fdp.ConsumeBool(); 82 83 int sr_pcm_hz = fdp.PickValueInArray(sr_list); 84 if (sr_pcm_hz < sr_hz) 85 sr_pcm_hz = 0; 86 87 Encoder enc(dt_us, sr_hz, sr_pcm_hz, nchannels, hrmode); 88 89 PcmFormat fmt = fdp.PickValueInArray( 90 { PcmFormat::kS16, PcmFormat::kS24, 91 PcmFormat::kS24In3Le, PcmFormat::kF32 }); 92 93 int frame_size = fdp.ConsumeIntegralInRange( 94 LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES); 95 96 switch (fmt) { 97 98 case PcmFormat::kS16: 99 return encode<int16_t>(enc, nchannels, frame_size, fdp); 100 101 case PcmFormat::kS24: { 102 const int32_t s24_min = -(1 << 23); 103 const int32_t s24_max = (1 << 23) - 1; 104 return encode<int32_t>(enc, nchannels, frame_size, fdp, s24_min, s24_max); 105 } 106 107 case PcmFormat::kF32: { 108 const float f32_min = -1.0; 109 const float f32_max = 1.0; 110 return encode<float>(enc, nchannels, frame_size, fdp, f32_min, f32_max); 111 } 112 113 case PcmFormat::kS24In3Le: 114 return encode(enc, nchannels, frame_size, fmt, fdp); 115 } 116 117 return 0; 118 } 119