diff options
Diffstat (limited to 'fuzzer/libldac_encode_fuzzer.cc')
-rw-r--r-- | fuzzer/libldac_encode_fuzzer.cc | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/fuzzer/libldac_encode_fuzzer.cc b/fuzzer/libldac_encode_fuzzer.cc new file mode 100644 index 0000000..501d177 --- /dev/null +++ b/fuzzer/libldac_encode_fuzzer.cc @@ -0,0 +1,110 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> +#include <stddef.h> +#include "ldacBT.h" + +#include <fuzzer/FuzzedDataProvider.h> +#include <vector> + +constexpr LDACBT_SMPL_FMT_T kFormat[] = { + LDACBT_SMPL_FMT_S16, LDACBT_SMPL_FMT_S24, LDACBT_SMPL_FMT_S32, + LDACBT_SMPL_FMT_F32}; +constexpr int32_t kEqmidValue[] = {LDACBT_EQMID_HQ, LDACBT_EQMID_SQ, + LDACBT_EQMID_MQ}; +constexpr int32_t kChannel[] = {LDACBT_CHANNEL_MODE_STEREO, + LDACBT_CHANNEL_MODE_DUAL_CHANNEL, + LDACBT_CHANNEL_MODE_MONO}; +constexpr int32_t kSamplingFrequency[] = {44100, 48000, 2 * 44100, 2 * 48000}; +constexpr int32_t kLdacBtRequiredMtu = 679; +constexpr int32_t kMaxWlValue = 4; +constexpr int32_t kMinChValue = 1; +constexpr int32_t kMaxChValue = 2; +constexpr int32_t kOutputSize = 1024; + +class Codec { +public: + Codec(const uint8_t *data, size_t size) : mFdp(data, size){}; + ~Codec() { deInitEncoder(); } + bool initEncoder(); + void deInitEncoder(); + void encodeFrames(const uint8_t *data, size_t size); + void getSamplingFrequeny(); + void getBitrate(); + void getVersion(); + FuzzedDataProvider mFdp; + +private: + int32_t mChannel; + LDACBT_SMPL_FMT_T mFormat; + HANDLE_LDAC_BT mHandleLdacBt; +}; + +bool Codec::initEncoder() { + mHandleLdacBt = ldacBT_get_handle(); + + mChannel = mFdp.PickValueInArray(kChannel); + mFormat = mFdp.PickValueInArray(kFormat); + int32_t status = ldacBT_init_handle_encode( + mHandleLdacBt, kLdacBtRequiredMtu, mFdp.PickValueInArray(kEqmidValue), + mChannel, mFormat, mFdp.PickValueInArray(kSamplingFrequency)); + if (!status) { + return true; + } + return false; +} + +void Codec::encodeFrames(const uint8_t *data, size_t size) { + int32_t pcmUsed, streamSize, frameNum; + unsigned char pStream[kOutputSize]; + int32_t ch, wl, frameSize; + ch = (mChannel == LDAC_CCI_MONO) ? kMinChValue : kMaxChValue; + wl = mFormat > kMaxWlValue ? kMaxWlValue : mFormat; + frameSize = LDACBT_ENC_LSU * ch * wl; + std::vector<uint8_t> tmpData(frameSize); + uint8_t *readPointer = const_cast<uint8_t *>(data); + while (size > 0) { + if (size < frameSize) { + memcpy(tmpData.data(), data, size); + size = frameSize; + readPointer = tmpData.data(); + } + ldacBT_encode(mHandleLdacBt, readPointer, &pcmUsed, pStream, &streamSize, + &frameNum); + readPointer += frameSize; + size -= frameSize; + } +} + +void Codec::getSamplingFrequeny() { ldacBT_get_sampling_freq(mHandleLdacBt); } + +void Codec::getBitrate() { ldacBT_get_bitrate(mHandleLdacBt); } + +void Codec::getVersion() { ldacBT_get_version(); } + +void Codec::deInitEncoder() { + ldacBT_close_handle(mHandleLdacBt); + ldacBT_free_handle(mHandleLdacBt); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t size) { + Codec codec(buf, size); + /* initEncoder() initializes mHandleLdacBt and is supposed to be called before + encoding begins. Hence initEncoder() is not included in the lambda + construct. */ + if (codec.initEncoder()) { + while (codec.mFdp.remaining_bytes() > 0) { + auto executeFunction = + codec.mFdp.PickValueInArray<const std::function<void()>>({ + [&]() { codec.encodeFrames(buf, size); }, + [&]() { codec.getSamplingFrequeny(); }, + [&]() { codec.getBitrate(); }, + [&]() { codec.getVersion(); }, + }); + executeFunction(); + } + } + return 0; +} |