xref: /aosp_15_r20/external/aac/fuzzer/aac_dec_fuzzer.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1*e5436536SAndroid Build Coastguard Worker /******************************************************************************
2*e5436536SAndroid Build Coastguard Worker  *
3*e5436536SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
4*e5436536SAndroid Build Coastguard Worker  *
5*e5436536SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*e5436536SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*e5436536SAndroid Build Coastguard Worker  * You may obtain a copy of the License at:
8*e5436536SAndroid Build Coastguard Worker  *
9*e5436536SAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
10*e5436536SAndroid Build Coastguard Worker  *
11*e5436536SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*e5436536SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*e5436536SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*e5436536SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*e5436536SAndroid Build Coastguard Worker  * limitations under the License.
16*e5436536SAndroid Build Coastguard Worker  *
17*e5436536SAndroid Build Coastguard Worker  *****************************************************************************
18*e5436536SAndroid Build Coastguard Worker  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*e5436536SAndroid Build Coastguard Worker  */
20*e5436536SAndroid Build Coastguard Worker 
21*e5436536SAndroid Build Coastguard Worker #include <stdint.h>
22*e5436536SAndroid Build Coastguard Worker #include <string.h>
23*e5436536SAndroid Build Coastguard Worker #include <algorithm>
24*e5436536SAndroid Build Coastguard Worker #include "aacdecoder_lib.h"
25*e5436536SAndroid Build Coastguard Worker 
26*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kNumberOfLayers = 1;
27*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kMaxChannelCount = 8;
28*e5436536SAndroid Build Coastguard Worker constexpr uint32_t kMaxConfigurationSize = 1024;
29*e5436536SAndroid Build Coastguard Worker constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount;
30*e5436536SAndroid Build Coastguard Worker 
31*e5436536SAndroid Build Coastguard Worker // Value indicating the start of AAC Header Segment
32*e5436536SAndroid Build Coastguard Worker constexpr const char *kAacSegStartSeq = "AAC_STRT";
33*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq);
34*e5436536SAndroid Build Coastguard Worker // Value indicating the end of AAC Header Segment
35*e5436536SAndroid Build Coastguard Worker constexpr const char *kAacSegEndSeq = "AAC_ENDS";
36*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq);
37*e5436536SAndroid Build Coastguard Worker 
38*e5436536SAndroid Build Coastguard Worker // Number of bytes used to signal the length of the header
39*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kHeaderLengthBytes = 2;
40*e5436536SAndroid Build Coastguard Worker // Minimum size of an AAC header is 2
41*e5436536SAndroid Build Coastguard Worker // Minimum data required is
42*e5436536SAndroid Build Coastguard Worker // strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2;
43*e5436536SAndroid Build Coastguard Worker constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2;
44*e5436536SAndroid Build Coastguard Worker 
getHeaderSize(UCHAR * data,UINT size)45*e5436536SAndroid Build Coastguard Worker UINT getHeaderSize(UCHAR *data, UINT size) {
46*e5436536SAndroid Build Coastguard Worker   if (size < kMinDataSize) {
47*e5436536SAndroid Build Coastguard Worker     return 0;
48*e5436536SAndroid Build Coastguard Worker   }
49*e5436536SAndroid Build Coastguard Worker 
50*e5436536SAndroid Build Coastguard Worker   int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen);
51*e5436536SAndroid Build Coastguard Worker   if (result) {
52*e5436536SAndroid Build Coastguard Worker     return 0;
53*e5436536SAndroid Build Coastguard Worker   }
54*e5436536SAndroid Build Coastguard Worker   data += kAacSegStartSeqLen;
55*e5436536SAndroid Build Coastguard Worker   size -= kAacSegStartSeqLen;
56*e5436536SAndroid Build Coastguard Worker 
57*e5436536SAndroid Build Coastguard Worker   uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF;
58*e5436536SAndroid Build Coastguard Worker   data += kHeaderLengthBytes;
59*e5436536SAndroid Build Coastguard Worker   size -= kHeaderLengthBytes;
60*e5436536SAndroid Build Coastguard Worker 
61*e5436536SAndroid Build Coastguard Worker   if (headerLengthInBytes + kAacSegEndSeqLen > size) {
62*e5436536SAndroid Build Coastguard Worker     return 0;
63*e5436536SAndroid Build Coastguard Worker   }
64*e5436536SAndroid Build Coastguard Worker 
65*e5436536SAndroid Build Coastguard Worker   data += headerLengthInBytes;
66*e5436536SAndroid Build Coastguard Worker   size -= headerLengthInBytes;
67*e5436536SAndroid Build Coastguard Worker   result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen);
68*e5436536SAndroid Build Coastguard Worker   if (result) {
69*e5436536SAndroid Build Coastguard Worker     return 0;
70*e5436536SAndroid Build Coastguard Worker   }
71*e5436536SAndroid Build Coastguard Worker 
72*e5436536SAndroid Build Coastguard Worker   return std::min(headerLengthInBytes, kMaxConfigurationSize);
73*e5436536SAndroid Build Coastguard Worker }
74*e5436536SAndroid Build Coastguard Worker 
75*e5436536SAndroid Build Coastguard Worker class Codec {
76*e5436536SAndroid Build Coastguard Worker  public:
77*e5436536SAndroid Build Coastguard Worker   Codec() = default;
~Codec()78*e5436536SAndroid Build Coastguard Worker   ~Codec() { deInitDecoder(); }
79*e5436536SAndroid Build Coastguard Worker   bool initDecoder();
80*e5436536SAndroid Build Coastguard Worker   void decodeFrames(UCHAR *data, UINT size);
81*e5436536SAndroid Build Coastguard Worker   void deInitDecoder();
82*e5436536SAndroid Build Coastguard Worker 
83*e5436536SAndroid Build Coastguard Worker  private:
84*e5436536SAndroid Build Coastguard Worker   HANDLE_AACDECODER mAacDecoderHandle = nullptr;
85*e5436536SAndroid Build Coastguard Worker   AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
86*e5436536SAndroid Build Coastguard Worker };
87*e5436536SAndroid Build Coastguard Worker 
initDecoder()88*e5436536SAndroid Build Coastguard Worker bool Codec::initDecoder() {
89*e5436536SAndroid Build Coastguard Worker   mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
90*e5436536SAndroid Build Coastguard Worker   if (!mAacDecoderHandle) {
91*e5436536SAndroid Build Coastguard Worker     return false;
92*e5436536SAndroid Build Coastguard Worker   }
93*e5436536SAndroid Build Coastguard Worker   return true;
94*e5436536SAndroid Build Coastguard Worker }
95*e5436536SAndroid Build Coastguard Worker 
deInitDecoder()96*e5436536SAndroid Build Coastguard Worker void Codec::deInitDecoder() {
97*e5436536SAndroid Build Coastguard Worker   aacDecoder_Close(mAacDecoderHandle);
98*e5436536SAndroid Build Coastguard Worker   mAacDecoderHandle = nullptr;
99*e5436536SAndroid Build Coastguard Worker }
100*e5436536SAndroid Build Coastguard Worker 
decodeFrames(UCHAR * data,UINT size)101*e5436536SAndroid Build Coastguard Worker void Codec::decodeFrames(UCHAR *data, UINT size) {
102*e5436536SAndroid Build Coastguard Worker   UINT headerSize = getHeaderSize(data, size);
103*e5436536SAndroid Build Coastguard Worker   if (headerSize != 0) {
104*e5436536SAndroid Build Coastguard Worker     data += kAacSegStartSeqLen + kHeaderLengthBytes;
105*e5436536SAndroid Build Coastguard Worker     size -= kAacSegStartSeqLen + kHeaderLengthBytes;
106*e5436536SAndroid Build Coastguard Worker     aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize);
107*e5436536SAndroid Build Coastguard Worker     data += headerSize + kAacSegEndSeqLen;
108*e5436536SAndroid Build Coastguard Worker     size -= headerSize + kAacSegEndSeqLen;
109*e5436536SAndroid Build Coastguard Worker   }
110*e5436536SAndroid Build Coastguard Worker   while (size > 0) {
111*e5436536SAndroid Build Coastguard Worker     UINT inputSize = size;
112*e5436536SAndroid Build Coastguard Worker     UINT valid = size;
113*e5436536SAndroid Build Coastguard Worker     mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
114*e5436536SAndroid Build Coastguard Worker     if (mErrorCode != AAC_DEC_OK) {
115*e5436536SAndroid Build Coastguard Worker       ++data;
116*e5436536SAndroid Build Coastguard Worker       --size;
117*e5436536SAndroid Build Coastguard Worker     } else {
118*e5436536SAndroid Build Coastguard Worker       INT_PCM outputBuf[kMaxOutBufferSize];
119*e5436536SAndroid Build Coastguard Worker       do {
120*e5436536SAndroid Build Coastguard Worker         mErrorCode =
121*e5436536SAndroid Build Coastguard Worker             aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
122*e5436536SAndroid Build Coastguard Worker                     kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0);
123*e5436536SAndroid Build Coastguard Worker       } while (mErrorCode == AAC_DEC_OK);
124*e5436536SAndroid Build Coastguard Worker       UINT offset = inputSize - valid;
125*e5436536SAndroid Build Coastguard Worker       data += offset;
126*e5436536SAndroid Build Coastguard Worker       size = valid;
127*e5436536SAndroid Build Coastguard Worker     }
128*e5436536SAndroid Build Coastguard Worker   }
129*e5436536SAndroid Build Coastguard Worker }
130*e5436536SAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)131*e5436536SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
132*e5436536SAndroid Build Coastguard Worker   Codec *codec = new Codec();
133*e5436536SAndroid Build Coastguard Worker   if (!codec) {
134*e5436536SAndroid Build Coastguard Worker     return 0;
135*e5436536SAndroid Build Coastguard Worker   }
136*e5436536SAndroid Build Coastguard Worker   if (codec->initDecoder()) {
137*e5436536SAndroid Build Coastguard Worker     codec->decodeFrames((UCHAR *)(data), static_cast<UINT>(size));
138*e5436536SAndroid Build Coastguard Worker   }
139*e5436536SAndroid Build Coastguard Worker   delete codec;
140*e5436536SAndroid Build Coastguard Worker   return 0;
141*e5436536SAndroid Build Coastguard Worker }
142