xref: /aosp_15_r20/external/aac/fuzzer/aac_dec_fuzzer.cpp (revision e54365361535b070c2db7374cec45c159c7d0e7a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2020 The Android Open Source Project
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  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 #include <stdint.h>
22 #include <string.h>
23 #include <algorithm>
24 #include "aacdecoder_lib.h"
25 
26 constexpr uint8_t kNumberOfLayers = 1;
27 constexpr uint8_t kMaxChannelCount = 8;
28 constexpr uint32_t kMaxConfigurationSize = 1024;
29 constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount;
30 
31 // Value indicating the start of AAC Header Segment
32 constexpr const char *kAacSegStartSeq = "AAC_STRT";
33 constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq);
34 // Value indicating the end of AAC Header Segment
35 constexpr const char *kAacSegEndSeq = "AAC_ENDS";
36 constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq);
37 
38 // Number of bytes used to signal the length of the header
39 constexpr uint8_t kHeaderLengthBytes = 2;
40 // Minimum size of an AAC header is 2
41 // Minimum data required is
42 // strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2;
43 constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2;
44 
getHeaderSize(UCHAR * data,UINT size)45 UINT getHeaderSize(UCHAR *data, UINT size) {
46   if (size < kMinDataSize) {
47     return 0;
48   }
49 
50   int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen);
51   if (result) {
52     return 0;
53   }
54   data += kAacSegStartSeqLen;
55   size -= kAacSegStartSeqLen;
56 
57   uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF;
58   data += kHeaderLengthBytes;
59   size -= kHeaderLengthBytes;
60 
61   if (headerLengthInBytes + kAacSegEndSeqLen > size) {
62     return 0;
63   }
64 
65   data += headerLengthInBytes;
66   size -= headerLengthInBytes;
67   result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen);
68   if (result) {
69     return 0;
70   }
71 
72   return std::min(headerLengthInBytes, kMaxConfigurationSize);
73 }
74 
75 class Codec {
76  public:
77   Codec() = default;
~Codec()78   ~Codec() { deInitDecoder(); }
79   bool initDecoder();
80   void decodeFrames(UCHAR *data, UINT size);
81   void deInitDecoder();
82 
83  private:
84   HANDLE_AACDECODER mAacDecoderHandle = nullptr;
85   AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
86 };
87 
initDecoder()88 bool Codec::initDecoder() {
89   mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
90   if (!mAacDecoderHandle) {
91     return false;
92   }
93   return true;
94 }
95 
deInitDecoder()96 void Codec::deInitDecoder() {
97   aacDecoder_Close(mAacDecoderHandle);
98   mAacDecoderHandle = nullptr;
99 }
100 
decodeFrames(UCHAR * data,UINT size)101 void Codec::decodeFrames(UCHAR *data, UINT size) {
102   UINT headerSize = getHeaderSize(data, size);
103   if (headerSize != 0) {
104     data += kAacSegStartSeqLen + kHeaderLengthBytes;
105     size -= kAacSegStartSeqLen + kHeaderLengthBytes;
106     aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize);
107     data += headerSize + kAacSegEndSeqLen;
108     size -= headerSize + kAacSegEndSeqLen;
109   }
110   while (size > 0) {
111     UINT inputSize = size;
112     UINT valid = size;
113     mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
114     if (mErrorCode != AAC_DEC_OK) {
115       ++data;
116       --size;
117     } else {
118       INT_PCM outputBuf[kMaxOutBufferSize];
119       do {
120         mErrorCode =
121             aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
122                     kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0);
123       } while (mErrorCode == AAC_DEC_OK);
124       UINT offset = inputSize - valid;
125       data += offset;
126       size = valid;
127     }
128   }
129 }
130 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)131 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
132   Codec *codec = new Codec();
133   if (!codec) {
134     return 0;
135   }
136   if (codec->initDecoder()) {
137     codec->decodeFrames((UCHAR *)(data), static_cast<UINT>(size));
138   }
139   delete codec;
140   return 0;
141 }
142