xref: /aosp_15_r20/external/libldac/fuzzer/libldac_encode_fuzzer.cc (revision aef9bcd9217ad2365ebc8e70efaf94b64e04df14)
1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdint.h>
6 #include <stddef.h>
7 #include "ldacBT.h"
8 
9 #include <functional>
10 #include <fuzzer/FuzzedDataProvider.h>
11 #include <vector>
12 
13 constexpr LDACBT_SMPL_FMT_T kFormat[] = {
14     LDACBT_SMPL_FMT_S16, LDACBT_SMPL_FMT_S24, LDACBT_SMPL_FMT_S32,
15     LDACBT_SMPL_FMT_F32};
16 constexpr int32_t kEqmidValue[] = {LDACBT_EQMID_HQ, LDACBT_EQMID_SQ,
17                                    LDACBT_EQMID_MQ};
18 constexpr int32_t kChannel[] = {LDACBT_CHANNEL_MODE_STEREO,
19                                 LDACBT_CHANNEL_MODE_DUAL_CHANNEL,
20                                 LDACBT_CHANNEL_MODE_MONO};
21 constexpr int32_t kSamplingFrequency[] = {44100, 48000, 2 * 44100, 2 * 48000};
22 constexpr int32_t kLdacBtRequiredMtu = 679;
23 constexpr int32_t kMaxWlValue = 4;
24 constexpr int32_t kMinChValue = 1;
25 constexpr int32_t kMaxChValue = 2;
26 constexpr int32_t kOutputSize = 1024;
27 
28 class Codec {
29 public:
Codec(const uint8_t * data,size_t size)30   Codec(const uint8_t *data, size_t size) : mFdp(data, size){};
~Codec()31   ~Codec() { deInitEncoder(); }
32   bool initEncoder();
33   void deInitEncoder();
34   void encodeFrames(const uint8_t *data, size_t size);
35   void getSamplingFrequeny();
36   void getBitrate();
37   void getVersion();
38   FuzzedDataProvider mFdp;
39 
40 private:
41   int32_t mChannel;
42   LDACBT_SMPL_FMT_T mFormat;
43   HANDLE_LDAC_BT mHandleLdacBt;
44 };
45 
initEncoder()46 bool Codec::initEncoder() {
47   mHandleLdacBt = ldacBT_get_handle();
48 
49   mChannel = mFdp.PickValueInArray(kChannel);
50   mFormat = mFdp.PickValueInArray(kFormat);
51   int32_t status = ldacBT_init_handle_encode(
52       mHandleLdacBt, kLdacBtRequiredMtu, mFdp.PickValueInArray(kEqmidValue),
53       mChannel, mFormat, mFdp.PickValueInArray(kSamplingFrequency));
54   if (!status) {
55     return true;
56   }
57   return false;
58 }
59 
encodeFrames(const uint8_t * data,size_t size)60 void Codec::encodeFrames(const uint8_t *data, size_t size) {
61   int32_t pcmUsed, streamSize, frameNum;
62   unsigned char pStream[kOutputSize];
63   int32_t ch, wl, frameSize;
64   ch = (mChannel == LDAC_CCI_MONO) ? kMinChValue : kMaxChValue;
65   wl = mFormat > kMaxWlValue ? kMaxWlValue : mFormat;
66   frameSize = LDACBT_ENC_LSU * ch * wl;
67   std::vector<uint8_t> tmpData(frameSize);
68   uint8_t *readPointer = const_cast<uint8_t *>(data);
69   while (size > 0) {
70     if (size < frameSize) {
71       memcpy(tmpData.data(), data, size);
72       size = frameSize;
73       readPointer = tmpData.data();
74     }
75     ldacBT_encode(mHandleLdacBt, readPointer, &pcmUsed, pStream, &streamSize,
76                   &frameNum);
77     readPointer += frameSize;
78     size -= frameSize;
79   }
80 }
81 
getSamplingFrequeny()82 void Codec::getSamplingFrequeny() { ldacBT_get_sampling_freq(mHandleLdacBt); }
83 
getBitrate()84 void Codec::getBitrate() { ldacBT_get_bitrate(mHandleLdacBt); }
85 
getVersion()86 void Codec::getVersion() { ldacBT_get_version(); }
87 
deInitEncoder()88 void Codec::deInitEncoder() {
89   ldacBT_close_handle(mHandleLdacBt);
90   ldacBT_free_handle(mHandleLdacBt);
91 }
92 
LLVMFuzzerTestOneInput(const uint8_t * buf,size_t size)93 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t size) {
94   Codec codec(buf, size);
95   /* initEncoder() initializes mHandleLdacBt and is supposed to be called before
96      encoding begins. Hence initEncoder() is not included in the lambda
97      construct. */
98   if (codec.initEncoder()) {
99     while (codec.mFdp.remaining_bytes() > 0) {
100       auto executeFunction =
101           codec.mFdp.PickValueInArray<const std::function<void()>>({
102               [&]() { codec.encodeFrames(buf, size); },
103               [&]() { codec.getSamplingFrequeny(); },
104               [&]() { codec.getBitrate(); },
105               [&]() { codec.getVersion(); },
106           });
107       executeFunction();
108     }
109   }
110   return 0;
111 }
112