1 /**
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fstream>
18 #include <iostream>
19 #include <limits>
20 #include "../includes/common.h"
21 #include "aacdecoder.h"
22 #include "aacdecoder_lib.h"
23 #include "sbr_ram.h"
24 
25 constexpr uint8_t kNumberOfLayers = 1;
26 constexpr uint8_t kMaxChannelCount = 8;
27 bool kIsVulnerable = false;
28 
29 class Codec {
30    public:
31     Codec() = default;
~Codec()32     ~Codec() { deInitDecoder(); }
33     bool initDecoder();
34     void decodeFrames(UCHAR *data, UINT size);
35     void deInitDecoder();
36     int validateQmfDomainBounds();
37 
38    private:
39     HANDLE_AACDECODER mAacDecoderHandle = nullptr;
40     AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
41 };
42 
initDecoder()43 bool Codec::initDecoder() {
44     mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
45     if (!mAacDecoderHandle) {
46         return false;
47     }
48     return true;
49 }
50 
deInitDecoder()51 void Codec::deInitDecoder() {
52     aacDecoder_Close(mAacDecoderHandle);
53     mAacDecoderHandle = nullptr;
54 }
55 
decodeFrames(UCHAR * data,UINT size)56 void Codec::decodeFrames(UCHAR *data, UINT size) {
57     while (size > 0) {
58         UINT inputSize = size;
59         UINT valid = size;
60         mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
61         if (mErrorCode != AAC_DEC_OK) {
62             ++data;
63             --size;
64         } else {
65             INT_PCM outputBuf[2048 * kMaxChannelCount];
66             aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf, 2048 * kMaxChannelCount, 0);
67             if (valid >= inputSize) {
68                 return;
69             }
70             UINT offset = inputSize - valid;
71             data += offset;
72             size = valid;
73         }
74     }
75 }
76 
validateQmfDomainBounds()77 int Codec::validateQmfDomainBounds() {
78     // Check OOB for qmfDomain
79     void *qmfDomainBound = &(mAacDecoderHandle->qmfModeCurr);
80 
81     HANDLE_SBRDECODER hSbrDecoder = mAacDecoderHandle->hSbrDecoder;
82     // Referring sbrDecoder_AssignQmfChannels2SbrChannels()
83     {
84         void *qmfDomainInChPtr = nullptr;
85         void *qmfDomainOutChPtr = nullptr;
86         int channel = 0;
87         int element = 0;
88         int absChOffset = 0;
89         for (element = 0; element < hSbrDecoder->numSbrElements; ++element) {
90             if (hSbrDecoder->pSbrElement[element] != NULL) {
91                 for (channel = 0; channel < hSbrDecoder->pSbrElement[element]->nChannels;
92                      ++channel) {
93                     qmfDomainInChPtr = &hSbrDecoder->pQmfDomain->QmfDomainIn[absChOffset + channel];
94                     qmfDomainOutChPtr =
95                         &hSbrDecoder->pQmfDomain->QmfDomainOut[absChOffset + channel];
96                     if (qmfDomainBound <= qmfDomainInChPtr || qmfDomainBound <= qmfDomainOutChPtr) {
97                         kIsVulnerable = true;
98                     }
99                 }
100                 absChOffset += hSbrDecoder->pSbrElement[element]->nChannels;
101             }
102         }
103     }
104     return kIsVulnerable ? EXIT_VULNERABLE : EXIT_SUCCESS;
105 }
106 
main(int argc,char * argv[])107 int main(int argc, char *argv[]) {
108     if (argc != 2) {
109         return EXIT_FAILURE;
110     }
111 
112     std::ifstream file;
113     file.open(argv[1], std::ios::in | std::ios::binary);
114     if (!file.is_open()) {
115         return EXIT_FAILURE;
116     }
117     file.ignore(std::numeric_limits<std::streamsize>::max());
118     std::streamsize length = file.gcount();
119     file.clear();
120     file.seekg(0, std::ios_base::beg);
121     UCHAR *data = new UCHAR[length];
122     file.read(reinterpret_cast<char *>(data), length);
123     file.close();
124 
125     Codec codec = Codec();
126     if (codec.initDecoder()) {
127         codec.decodeFrames(data, length);
128     }
129     return codec.validateQmfDomainBounds();
130 }
131