/* * Copyright (C) 2021 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. * */ #include #include #include #include #include #include #include using namespace std; using namespace android; const char *kMimeTypes[] = {MEDIA_MIMETYPE_IMAGE_JPEG, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9, MEDIA_MIMETYPE_VIDEO_AV1, MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_HEVC, MEDIA_MIMETYPE_VIDEO_MPEG4, MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_VIDEO_MPEG2, MEDIA_MIMETYPE_VIDEO_RAW, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, MEDIA_MIMETYPE_VIDEO_SCRAMBLED, MEDIA_MIMETYPE_VIDEO_DIVX, MEDIA_MIMETYPE_VIDEO_DIVX3, MEDIA_MIMETYPE_VIDEO_XVID, MEDIA_MIMETYPE_VIDEO_MJPEG, MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB, MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II, MEDIA_MIMETYPE_AUDIO_MIDI, MEDIA_MIMETYPE_AUDIO_AAC, MEDIA_MIMETYPE_AUDIO_QCELP, MEDIA_MIMETYPE_AUDIO_VORBIS, MEDIA_MIMETYPE_AUDIO_OPUS, MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_G711_MLAW, MEDIA_MIMETYPE_AUDIO_RAW, MEDIA_MIMETYPE_AUDIO_FLAC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS, MEDIA_MIMETYPE_AUDIO_MSGSM, MEDIA_MIMETYPE_AUDIO_AC3, MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_EAC3_JOC, MEDIA_MIMETYPE_AUDIO_AC4, MEDIA_MIMETYPE_AUDIO_SCRAMBLED, MEDIA_MIMETYPE_AUDIO_ALAC, MEDIA_MIMETYPE_AUDIO_WMA, MEDIA_MIMETYPE_AUDIO_MS_ADPCM, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM, MEDIA_MIMETYPE_CONTAINER_MPEG4, MEDIA_MIMETYPE_CONTAINER_WAV, MEDIA_MIMETYPE_CONTAINER_OGG, MEDIA_MIMETYPE_CONTAINER_MATROSKA, MEDIA_MIMETYPE_CONTAINER_MPEG2TS, MEDIA_MIMETYPE_CONTAINER_AVI, MEDIA_MIMETYPE_CONTAINER_MPEG2PS, MEDIA_MIMETYPE_CONTAINER_HEIF, MEDIA_MIMETYPE_TEXT_3GPP, MEDIA_MIMETYPE_TEXT_SUBRIP, MEDIA_MIMETYPE_TEXT_VTT, MEDIA_MIMETYPE_TEXT_CEA_608, MEDIA_MIMETYPE_TEXT_CEA_708, MEDIA_MIMETYPE_DATA_TIMED_ID3}; class MetadataRetrieverFuzzer { public: MetadataRetrieverFuzzer(const uint8_t *data, size_t size) : mFdp(data, size), mMdRetriever(new StagefrightMetadataRetriever()), mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)) {} ~MetadataRetrieverFuzzer() { close(mDataSourceFd); } bool setDataSource(const uint8_t *data, size_t size); void getData(); private: FuzzedDataProvider mFdp; sp mMdRetriever = nullptr; const int32_t mDataSourceFd; }; void MetadataRetrieverFuzzer::getData() { int64_t timeUs = mFdp.ConsumeIntegral(); int32_t option = mFdp.ConsumeIntegral(); int32_t colorFormat = mFdp.ConsumeIntegral(); bool metaOnly = mFdp.ConsumeBool(); mMdRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly); int32_t index = mFdp.ConsumeIntegral(); colorFormat = mFdp.ConsumeIntegral(); metaOnly = mFdp.ConsumeBool(); bool thumbnail = mFdp.ConsumeBool(); mMdRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail); index = mFdp.ConsumeIntegral(); colorFormat = mFdp.ConsumeIntegral(); int32_t left = mFdp.ConsumeIntegral(); int32_t top = mFdp.ConsumeIntegral(); int32_t right = mFdp.ConsumeIntegral(); int32_t bottom = mFdp.ConsumeIntegral(); mMdRetriever->getImageRectAtIndex(index, colorFormat, left, top, right, bottom); index = mFdp.ConsumeIntegral(); colorFormat = mFdp.ConsumeIntegral(); metaOnly = mFdp.ConsumeBool(); mMdRetriever->getFrameAtIndex(index, colorFormat, metaOnly); mMdRetriever->extractAlbumArt(); int32_t keyCode = mFdp.ConsumeIntegral(); mMdRetriever->extractMetadata(keyCode); } bool MetadataRetrieverFuzzer::setDataSource(const uint8_t *data, size_t size) { status_t status = -1; enum DataSourceChoice {FromHttp, FromFd, FromFileSource, kMaxValue = FromFileSource}; switch (mFdp.ConsumeEnum()) { case FromHttp: { KeyedVector mHeaders; mHeaders.add(String8(mFdp.ConsumeRandomLengthString().c_str()), String8(mFdp.ConsumeRandomLengthString().c_str())); uint32_t dataBlobSize = mFdp.ConsumeIntegralInRange(0, size); vector uriSuffix = mFdp.ConsumeBytes(dataBlobSize); string uri("data:"); uri += ";base64,"; AString out; encodeBase64(uriSuffix.data(), uriSuffix.size(), &out); uri += out.c_str(); status = mMdRetriever->setDataSource(nullptr /*httpService*/, uri.c_str(), &mHeaders); break; } case FromFd: { write(mDataSourceFd, data, size); status = mMdRetriever->setDataSource(mDataSourceFd, 0, size); break; } case FromFileSource: { write(mDataSourceFd, data, size); sp dataSource = new FileSource(dup(mDataSourceFd), 0, size); status = mMdRetriever->setDataSource(dataSource, mFdp.PickValueInArray(kMimeTypes)); break; } } if (status != 0) { return false; } return true; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { MetadataRetrieverFuzzer mrtFuzzer(data, size); ProcessState::self()->startThreadPool(); if (mrtFuzzer.setDataSource(data, size)) { mrtFuzzer.getData(); } return 0; }