/****************************************************************************** * * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ #include #include #include "gsmamr_dec.h" // Constants for AMR-NB constexpr int32_t kSamplesPerFrame = L_FRAME; constexpr int32_t kBitsPerSample = 16; constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8; const bitstream_format kBitStreamFormats[2] = {MIME_IETF, IF2}; const int32_t kLocalWmfDecBytesPerFrame[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0}; const int32_t kLocalIf2DecBytesPerFrame[16] = {13, 14, 16, 18, 19, 21, 26, 31, 13, 14, 16, 18, 19, 21, 26, 31}; class Codec { public: Codec() = default; ~Codec() { deInitDecoder(); } int16_t initDecoder(); void deInitDecoder(); void decodeFrames(const uint8_t *data, size_t size); private: void *mAmrHandle = nullptr; }; int16_t Codec::initDecoder() { return GSMInitDecode(&mAmrHandle, (Word8 *)"AMRNBDecoder"); } void Codec::deInitDecoder() { GSMDecodeFrameExit(&mAmrHandle); } void Codec::decodeFrames(const uint8_t *data, size_t size) { while (size > 0) { uint8_t mode = *data; bool bit = mode & 0x01; bitstream_format bitsreamFormat = kBitStreamFormats[bit]; int32_t frameSize = 0; /* Find frame type */ Frame_Type_3GPP frameType = static_cast((mode >> 3) & 0x0f); ++data; --size; if (bit) { frameSize = kLocalIf2DecBytesPerFrame[frameType]; } else { frameSize = kLocalWmfDecBytesPerFrame[frameType]; } int16_t outputBuf[kOutputBufferSize]; uint8_t *inputBuf = new uint8_t[frameSize]; if (!inputBuf) { return; } int32_t minSize = std::min((int32_t)size, frameSize); memcpy(inputBuf, data, minSize); AMRDecode(mAmrHandle, frameType, inputBuf, outputBuf, bitsreamFormat); /* AMRDecode() decodes minSize number of bytes if decode is successful. * AMRDecode() returns -1 if decode fails. * Even if no bytes are decoded, increment by minSize to ensure fuzzer proceeds * to feed next data */ data += minSize; size -= minSize; delete[] inputBuf; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 2) { return 0; } Codec *codec = new Codec(); if (!codec) { return 0; } if (codec->initDecoder() == 0) { codec->decodeFrames(data, size); } delete codec; return 0; }