1*bda690e4SXin Li /******************************************************************************
2*bda690e4SXin Li *
3*bda690e4SXin Li * Copyright (C) 2020 The Android Open Source Project
4*bda690e4SXin Li *
5*bda690e4SXin Li * Licensed under the Apache License, Version 2.0 (the "License");
6*bda690e4SXin Li * you may not use this file except in compliance with the License.
7*bda690e4SXin Li * You may obtain a copy of the License at:
8*bda690e4SXin Li *
9*bda690e4SXin Li * http://www.apache.org/licenses/LICENSE-2.0
10*bda690e4SXin Li *
11*bda690e4SXin Li * Unless required by applicable law or agreed to in writing, software
12*bda690e4SXin Li * distributed under the License is distributed on an "AS IS" BASIS,
13*bda690e4SXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*bda690e4SXin Li * See the License for the specific language governing permissions and
15*bda690e4SXin Li * limitations under the License.
16*bda690e4SXin Li *
17*bda690e4SXin Li *****************************************************************************
18*bda690e4SXin Li * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*bda690e4SXin Li */
20*bda690e4SXin Li
21*bda690e4SXin Li #include <stdint.h>
22*bda690e4SXin Li #include <string.h>
23*bda690e4SXin Li extern "C" {
24*bda690e4SXin Li #include <Tremolo/codec_internal.h>
25*bda690e4SXin Li
26*bda690e4SXin Li int _vorbis_unpack_books(vorbis_info *vi, oggpack_buffer *opb);
27*bda690e4SXin Li int _vorbis_unpack_info(vorbis_info *vi, oggpack_buffer *opb);
28*bda690e4SXin Li int _vorbis_unpack_comment(vorbis_comment *vc, oggpack_buffer *opb);
29*bda690e4SXin Li }
30*bda690e4SXin Li
31*bda690e4SXin Li constexpr int16_t kMaxNumSamplesPerChannel = 8192;
32*bda690e4SXin Li constexpr size_t kVorbisHeaderlength = 7;
33*bda690e4SXin Li
34*bda690e4SXin Li class Codec {
35*bda690e4SXin Li public:
36*bda690e4SXin Li Codec() = default;
~Codec()37*bda690e4SXin Li ~Codec() { deInitDecoder(); }
38*bda690e4SXin Li bool initDecoder();
39*bda690e4SXin Li void decodeFrames(const uint8_t *data, size_t size);
40*bda690e4SXin Li void deInitDecoder();
41*bda690e4SXin Li
42*bda690e4SXin Li private:
43*bda690e4SXin Li bool mInfoUnpacked = false;
44*bda690e4SXin Li bool mBooksUnpacked = false;
45*bda690e4SXin Li int32_t mNumFramesLeftOnPage = -1;
46*bda690e4SXin Li vorbis_dsp_state *mState = nullptr;
47*bda690e4SXin Li vorbis_info *mVi = nullptr;
48*bda690e4SXin Li };
49*bda690e4SXin Li
initDecoder()50*bda690e4SXin Li bool Codec::initDecoder() {
51*bda690e4SXin Li mVi = new vorbis_info{};
52*bda690e4SXin Li if (!mVi) {
53*bda690e4SXin Li return false;
54*bda690e4SXin Li }
55*bda690e4SXin Li vorbis_info_clear(mVi);
56*bda690e4SXin Li
57*bda690e4SXin Li mState = new vorbis_dsp_state{};
58*bda690e4SXin Li if (!mState) {
59*bda690e4SXin Li return false;
60*bda690e4SXin Li }
61*bda690e4SXin Li vorbis_dsp_clear(mState);
62*bda690e4SXin Li
63*bda690e4SXin Li mNumFramesLeftOnPage = -1;
64*bda690e4SXin Li mInfoUnpacked = false;
65*bda690e4SXin Li mBooksUnpacked = false;
66*bda690e4SXin Li
67*bda690e4SXin Li return true;
68*bda690e4SXin Li }
69*bda690e4SXin Li
makeBitReader(const uint8_t * data,size_t size,ogg_buffer * buf,ogg_reference * ref,oggpack_buffer * bits)70*bda690e4SXin Li static void makeBitReader(const uint8_t *data, size_t size, ogg_buffer *buf, ogg_reference *ref,
71*bda690e4SXin Li oggpack_buffer *bits) {
72*bda690e4SXin Li buf->data = const_cast<uint8_t *>(data);
73*bda690e4SXin Li buf->size = size;
74*bda690e4SXin Li buf->refcount = 1;
75*bda690e4SXin Li buf->ptr.owner = nullptr;
76*bda690e4SXin Li
77*bda690e4SXin Li ref->buffer = buf;
78*bda690e4SXin Li ref->begin = 0;
79*bda690e4SXin Li ref->length = size;
80*bda690e4SXin Li ref->next = nullptr;
81*bda690e4SXin Li
82*bda690e4SXin Li oggpack_readinit(bits, ref);
83*bda690e4SXin Li }
84*bda690e4SXin Li
decodeFrames(const uint8_t * data,size_t size)85*bda690e4SXin Li void Codec::decodeFrames(const uint8_t *data, size_t size) {
86*bda690e4SXin Li /* Decode vorbis headers only once */
87*bda690e4SXin Li while (size > 0) {
88*bda690e4SXin Li if (size > kVorbisHeaderlength && (!memcmp(&data[1], "vorbis", 6)) &&
89*bda690e4SXin Li (!mInfoUnpacked || !mBooksUnpacked)) {
90*bda690e4SXin Li if ((data[0] == 1) || (data[0] == 5)) {
91*bda690e4SXin Li ogg_buffer buf;
92*bda690e4SXin Li ogg_reference ref;
93*bda690e4SXin Li oggpack_buffer bits;
94*bda690e4SXin Li /* skip kVorbisHeaderlength <type + "vorbis"> bytes */
95*bda690e4SXin Li makeBitReader(data + kVorbisHeaderlength, size - kVorbisHeaderlength, &buf, &ref, &bits);
96*bda690e4SXin Li if (data[0] == 1) {
97*bda690e4SXin Li // release any memory that vorbis_info_init will blindly overwrite
98*bda690e4SXin Li vorbis_info_clear(mVi);
99*bda690e4SXin Li vorbis_info_init(mVi);
100*bda690e4SXin Li if (0 != _vorbis_unpack_info(mVi, &bits)) {
101*bda690e4SXin Li return;
102*bda690e4SXin Li }
103*bda690e4SXin Li mInfoUnpacked = true;
104*bda690e4SXin Li } else { /* data[0] == 5*/
105*bda690e4SXin Li if (!mInfoUnpacked) {
106*bda690e4SXin Li return;
107*bda690e4SXin Li }
108*bda690e4SXin Li if (0 != _vorbis_unpack_books(mVi, &bits)) {
109*bda690e4SXin Li return;
110*bda690e4SXin Li }
111*bda690e4SXin Li // release any memory that vorbis_dsp_init will blindly overwrite
112*bda690e4SXin Li vorbis_dsp_clear(mState);
113*bda690e4SXin Li if (0 != vorbis_dsp_init(mState, mVi)) {
114*bda690e4SXin Li return;
115*bda690e4SXin Li }
116*bda690e4SXin Li mBooksUnpacked = true;
117*bda690e4SXin Li data += kVorbisHeaderlength;
118*bda690e4SXin Li size -= kVorbisHeaderlength;
119*bda690e4SXin Li break;
120*bda690e4SXin Li }
121*bda690e4SXin Li }
122*bda690e4SXin Li }
123*bda690e4SXin Li ++data;
124*bda690e4SXin Li --size;
125*bda690e4SXin Li }
126*bda690e4SXin Li
127*bda690e4SXin Li if (!mInfoUnpacked || !mBooksUnpacked) {
128*bda690e4SXin Li return;
129*bda690e4SXin Li }
130*bda690e4SXin Li
131*bda690e4SXin Li int32_t numPageFrames = 0;
132*bda690e4SXin Li if (size < sizeof(numPageFrames)) {
133*bda690e4SXin Li return;
134*bda690e4SXin Li }
135*bda690e4SXin Li memcpy(&numPageFrames, data + size - sizeof(numPageFrames), sizeof(numPageFrames));
136*bda690e4SXin Li size -= sizeof(numPageFrames);
137*bda690e4SXin Li if (numPageFrames >= 0) {
138*bda690e4SXin Li mNumFramesLeftOnPage = numPageFrames;
139*bda690e4SXin Li }
140*bda690e4SXin Li
141*bda690e4SXin Li ogg_buffer buf;
142*bda690e4SXin Li buf.data = const_cast<unsigned char *>(data);
143*bda690e4SXin Li buf.size = size;
144*bda690e4SXin Li buf.refcount = 1;
145*bda690e4SXin Li buf.ptr.owner = nullptr;
146*bda690e4SXin Li
147*bda690e4SXin Li ogg_reference ref;
148*bda690e4SXin Li ref.buffer = &buf;
149*bda690e4SXin Li ref.begin = 0;
150*bda690e4SXin Li ref.length = buf.size;
151*bda690e4SXin Li ref.next = nullptr;
152*bda690e4SXin Li
153*bda690e4SXin Li ogg_packet pack;
154*bda690e4SXin Li pack.packet = &ref;
155*bda690e4SXin Li pack.bytes = ref.length;
156*bda690e4SXin Li pack.b_o_s = 0;
157*bda690e4SXin Li pack.e_o_s = 0;
158*bda690e4SXin Li pack.granulepos = 0;
159*bda690e4SXin Li pack.packetno = 0;
160*bda690e4SXin Li
161*bda690e4SXin Li int ret = vorbis_dsp_synthesis(mState, &pack, 1);
162*bda690e4SXin Li if (0 == ret) {
163*bda690e4SXin Li size_t maxSamplesInBuffer = kMaxNumSamplesPerChannel * mVi->channels;
164*bda690e4SXin Li size_t outCapacity = maxSamplesInBuffer * sizeof(int16_t);
165*bda690e4SXin Li int16_t outputBuf[outCapacity];
166*bda690e4SXin Li vorbis_dsp_pcmout(mState, outputBuf, kMaxNumSamplesPerChannel);
167*bda690e4SXin Li }
168*bda690e4SXin Li }
169*bda690e4SXin Li
deInitDecoder()170*bda690e4SXin Li void Codec::deInitDecoder() {
171*bda690e4SXin Li if (mState) {
172*bda690e4SXin Li vorbis_dsp_clear(mState);
173*bda690e4SXin Li delete mState;
174*bda690e4SXin Li mState = nullptr;
175*bda690e4SXin Li }
176*bda690e4SXin Li
177*bda690e4SXin Li if (mVi) {
178*bda690e4SXin Li vorbis_info_clear(mVi);
179*bda690e4SXin Li delete mVi;
180*bda690e4SXin Li mVi = nullptr;
181*bda690e4SXin Li }
182*bda690e4SXin Li }
183*bda690e4SXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)184*bda690e4SXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
185*bda690e4SXin Li if (size < kVorbisHeaderlength + 1) { /* 7 bytes for header , at least 1 byte for data */
186*bda690e4SXin Li return 0;
187*bda690e4SXin Li }
188*bda690e4SXin Li Codec *codec = new Codec();
189*bda690e4SXin Li if (!codec) {
190*bda690e4SXin Li return 0;
191*bda690e4SXin Li }
192*bda690e4SXin Li if (codec->initDecoder()) {
193*bda690e4SXin Li codec->decodeFrames(data, size);
194*bda690e4SXin Li }
195*bda690e4SXin Li delete codec;
196*bda690e4SXin Li return 0;
197*bda690e4SXin Li }
198