diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-04-18 05:17:27 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-04-18 05:17:27 +0000 |
commit | dfe71bf739eb11f23c566d4aa252ed0865e0f96e (patch) | |
tree | fee76a6e20511c3517a7d47c7424eb2e2a39a8d9 | |
parent | 887d0679962a55a898944c1655645bf240620b0c (diff) | |
parent | 77171a1421e98a9091578ba5e12cb9d94660da98 (diff) | |
download | av-dfe71bf739eb11f23c566d4aa252ed0865e0f96e.tar.gz |
Merge "Refactored libstagefright_frameDecoder_fuzzer" into main
11 files changed, 193 insertions, 138 deletions
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp index 4218d2d7d5..3f850c2814 100644 --- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp +++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp @@ -24,61 +24,64 @@ namespace android { -#define MAX_MEDIA_BUFFER_SIZE 2048 +static const android_pixel_format_t kColorFormats[] = { + HAL_PIXEL_FORMAT_RGBA_8888, + HAL_PIXEL_FORMAT_RGB_565, + HAL_PIXEL_FORMAT_BGRA_8888, + HAL_PIXEL_FORMAT_RGBA_1010102, + HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, /* To cover the default case */ +}; -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - // Init our wrapper - FuzzedDataProvider fdp(data, size); +static const MediaSource::ReadOptions::SeekMode kSeekModes[] = { + MediaSource::ReadOptions::SeekMode::SEEK_PREVIOUS_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_NEXT_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST_SYNC, + MediaSource::ReadOptions::SeekMode::SEEK_CLOSEST, + MediaSource::ReadOptions::SeekMode::SEEK_FRAME_INDEX, +}; + +static const std::string kComponentNames[] = { + "c2.android.avc.decoder", "c2.android.hevc.decoder", "c2.android.vp8.decoder", + "c2.android.vp9.decoder", "c2.android.av1.decoder", "c2.android.mpeg4.decoder", + "c2.android.h263.decoder", +}; - std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); - AString componentName(name.c_str()); - sp<MetaData> trackMeta = generateMetaData(&fdp); - sp<IMediaSource> source = new IMediaSourceFuzzImpl(&fdp, MAX_MEDIA_BUFFER_SIZE); +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + std::string component = fdp.PickValueInArray(kComponentNames); + AString componentName(component.c_str()); + sp<MetaData> trackMeta = generateMetaData(&fdp, component); + sp<IMediaSource> source = sp<IMediaSourceFuzzImpl>::make(&fdp, gMaxMediaBufferSize); - // Image or video Decoder? - sp<FrameDecoder> decoder; - bool isVideoDecoder = fdp.ConsumeBool(); - if (isVideoDecoder) { - decoder = new VideoFrameDecoder(componentName, trackMeta, source); + sp<FrameDecoder> decoder = nullptr; + if (fdp.ConsumeBool()) { + decoder = sp<MediaImageDecoder>::make(componentName, trackMeta, source); } else { - decoder = new MediaImageDecoder(componentName, trackMeta, source); + decoder = sp<VideoFrameDecoder>::make(componentName, trackMeta, source); } - while (fdp.remaining_bytes()) { - uint8_t switchCase = fdp.ConsumeIntegralInRange<uint8_t>(0, 3); - switch (switchCase) { - case 0: { - int64_t frameTimeUs = fdp.ConsumeIntegral<int64_t>(); - int option = fdp.ConsumeIntegral<int>(); - int colorFormat = fdp.ConsumeIntegral<int>(); - decoder->init(frameTimeUs, option, colorFormat); - break; - } - case 1: - decoder->extractFrame(); - break; - case 2: { - FrameRect rect; - rect.left = fdp.ConsumeIntegral<int32_t>(); - rect.top = fdp.ConsumeIntegral<int32_t>(); - rect.right = fdp.ConsumeIntegral<int32_t>(); - rect.bottom = fdp.ConsumeIntegral<int32_t>(); - decoder->extractFrame(&rect); - break; - } - case 3: { - sp<MetaData> trackMeta = generateMetaData(&fdp); - decoder->getMetadataOnly(trackMeta, - /*colorFormat*/ fdp.ConsumeIntegral<int>(), - /*thumbnail*/ fdp.ConsumeBool()); - break; - } - } + if (decoder.get() && + decoder->init(fdp.ConsumeIntegral<uint64_t>() /* frameTimeUs */, + fdp.PickValueInArray(kSeekModes) /* option */, + fdp.PickValueInArray(kColorFormats) /* colorFormat */) == OK) { + auto frameDecoderAPI = fdp.PickValueInArray<const std::function<void()>>({ + [&]() { decoder->extractFrame(); }, + [&]() { + FrameRect rect(fdp.ConsumeIntegral<int32_t>() /* left */, + fdp.ConsumeIntegral<int32_t>() /* top */, + fdp.ConsumeIntegral<int32_t>() /* right */, + fdp.ConsumeIntegral<int32_t>() /* bottom */ + ); + decoder->extractFrame(&rect); + }, + [&]() { + FrameDecoder::getMetadataOnly( + trackMeta, fdp.PickValueInArray(kColorFormats) /* colorFormat */, + fdp.ConsumeBool() /* thumbnail */); + }, + }); + frameDecoderAPI(); } - - generated_mime_types.clear(); - return 0; } diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h index 228c04a13c..5430530be9 100644 --- a/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h +++ b/media/libstagefright/tests/fuzzers/FrameDecoderHelpers.h @@ -20,69 +20,100 @@ #include <media/stagefright/MetaData.h> #include "MediaMimeTypes.h" -#define MAX_METADATA_BUF_SIZE 512 - namespace android { std::vector<std::shared_ptr<char>> generated_mime_types; +constexpr uint8_t kMinKeyHeight = 32; +constexpr uint8_t kMinKeyWidth = 32; +constexpr uint16_t kMaxKeyHeight = 2160; +constexpr uint16_t kMaxKeyWidth = 3840; +size_t gMaxMediaBufferSize = 0; + +sp<MetaData> generateMetaData(FuzzedDataProvider* fdp, std::string componentName = std::string()) { + sp<MetaData> newMeta = sp<MetaData>::make(); + + const char* mime; + if(!componentName.empty()) + { + auto it = decoderToMediaType.find(componentName); + mime = it->second; + } + else{ + size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size()); + // Let there be a chance of a true random string + if (index == kMimeTypes.size()) { + std::string mime_str = fdp->ConsumeRandomLengthString(64); + std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]); + generated_mime_types.push_back(mime_cstr); + strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1); + mime = mime_cstr.get(); + } else { + mime = kMimeTypes[index]; + } + } + newMeta->setCString(kKeyMIMEType, mime); + + auto height = fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyHeight, kMaxKeyHeight); + auto width = fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyWidth, kMaxKeyWidth); + newMeta->setInt32(kKeyHeight, height); + newMeta->setInt32(kKeyWidth, width); + + gMaxMediaBufferSize = height * width; + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyTileHeight, + fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyHeight, height)); + newMeta->setInt32(kKeyTileWidth, + fdp->ConsumeIntegralInRange<uint16_t>(kMinKeyWidth, width)); + newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<uint8_t>()); + newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<uint8_t>()); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<uint8_t>()); + newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<uint8_t>()); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyDisplayHeight, + fdp->ConsumeIntegralInRange<uint16_t>(height, UINT16_MAX)); + newMeta->setInt32(kKeyDisplayWidth, + fdp->ConsumeIntegralInRange<uint16_t>(width, UINT16_MAX)); + } + + if (fdp->ConsumeBool()) { + newMeta->setRect(kKeyCropRect, fdp->ConsumeIntegral<int32_t>() /* left */, + fdp->ConsumeIntegral<int32_t>() /* top */, + fdp->ConsumeIntegral<int32_t>() /* right */, + fdp->ConsumeIntegral<int32_t>() /* bottom */); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegralInRange<uint8_t>(0, 3) * 90); + } + + if (fdp->ConsumeBool()) { + newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<uint64_t>()); + newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<uint8_t>()); + newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<uint8_t>()); + + size_t thumbnailSize = fdp->ConsumeIntegral<size_t>(); + std::vector<uint8_t> thumbnailData = fdp->ConsumeBytes<uint8_t>(thumbnailSize); + if (mime == MEDIA_MIMETYPE_VIDEO_AV1) { + newMeta->setData(kKeyThumbnailAV1C, fdp->ConsumeIntegral<int32_t>() /* type */, + thumbnailData.data(), thumbnailData.size()); + } else { + newMeta->setData(kKeyThumbnailHVCC, fdp->ConsumeIntegral<int32_t>() /* type */, + thumbnailData.data(), thumbnailData.size()); + } + } -sp<MetaData> generateMetaData(FuzzedDataProvider *fdp) { - sp<MetaData> newMeta = new MetaData(); - - // random MIME Type - const char *mime_type; - size_t index = fdp->ConsumeIntegralInRange<size_t>(0, kMimeTypes.size()); - // Let there be a chance of a true random string - if (index == kMimeTypes.size()) { - std::string mime_str = fdp->ConsumeRandomLengthString(64); - std::shared_ptr<char> mime_cstr(new char[mime_str.length()+1]); - generated_mime_types.push_back(mime_cstr); - strncpy(mime_cstr.get(), mime_str.c_str(), mime_str.length()+1); - mime_type = mime_cstr.get(); - } else { - mime_type = kMimeTypes[index]; + if (fdp->ConsumeBool()) { + size_t profileSize = fdp->ConsumeIntegral<size_t>(); + std::vector<uint8_t> profileData = fdp->ConsumeBytes<uint8_t>(profileSize); + newMeta->setData(kKeyIccProfile, fdp->ConsumeIntegral<int32_t>() /* type */, + profileData.data(), profileData.size()); } - newMeta->setCString(kKeyMIMEType, mime_type); - - // Thumbnail time - newMeta->setInt64(kKeyThumbnailTime, fdp->ConsumeIntegral<int64_t>()); - - // Values used by allocVideoFrame - newMeta->setInt32(kKeyRotation, fdp->ConsumeIntegral<int32_t>()); - size_t profile_size = - fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE); - std::vector<uint8_t> profile_bytes = - fdp->ConsumeBytes<uint8_t>(profile_size); - newMeta->setData(kKeyIccProfile, - fdp->ConsumeIntegral<int32_t>(), - profile_bytes.empty() ? nullptr : profile_bytes.data(), - profile_bytes.size()); - newMeta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<int32_t>()); - - // Values used by findThumbnailInfo - newMeta->setInt32(kKeyThumbnailWidth, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyThumbnailHeight, fdp->ConsumeIntegral<int32_t>()); - size_t thumbnail_size = - fdp->ConsumeIntegralInRange<size_t>(0, MAX_METADATA_BUF_SIZE); - std::vector<uint8_t> thumb_bytes = - fdp->ConsumeBytes<uint8_t>(thumbnail_size); - newMeta->setData(kKeyThumbnailHVCC, - fdp->ConsumeIntegral<int32_t>(), - thumb_bytes.empty() ? nullptr : thumb_bytes.data(), - thumb_bytes.size()); - - // Values used by findGridInfo - newMeta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<int32_t>()); - - // A few functions perform a CHECK() that height/width are set - newMeta->setInt32(kKeyHeight, fdp->ConsumeIntegral<int32_t>()); - newMeta->setInt32(kKeyWidth, fdp->ConsumeIntegral<int32_t>()); return newMeta; } diff --git a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h index e769950f82..7e6f662098 100644 --- a/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h +++ b/media/libstagefright/tests/fuzzers/IMediaSourceFuzzImpl.h @@ -19,31 +19,33 @@ #include <media/stagefright/MediaSource.h> +#define MAX_FRAMES 5 + namespace android { class IMediaSourceFuzzImpl : public IMediaSource { public: - IMediaSourceFuzzImpl(FuzzedDataProvider *_fdp, size_t _max_buffer_size) : - fdp(_fdp), - max_buffer_size(_max_buffer_size) {} - status_t start(MetaData*) override { return 0; } - status_t stop() override { return 0; } - sp<MetaData> getFormat() override { return nullptr; } - status_t read(MediaBufferBase**, - const MediaSource::ReadOptions*) override; - status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t, - const MediaSource::ReadOptions*) override; - bool supportReadMultiple() override { return true; } - bool supportNonblockingRead() override { return true; } - status_t pause() override { return 0; } + IMediaSourceFuzzImpl(FuzzedDataProvider* _fdp, size_t _max_buffer_size) + : frames_read(0), fdp(_fdp), min_buffer_size(32 * 32), max_buffer_size(_max_buffer_size) {} + status_t start(MetaData*) override { return 0; } + status_t stop() override { return 0; } + sp<MetaData> getFormat() override { return nullptr; } + status_t read(MediaBufferBase**, const MediaSource::ReadOptions*) override; + status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t, + const MediaSource::ReadOptions*) override; + bool supportReadMultiple() override { return true; } + bool supportNonblockingRead() override { return true; } + status_t pause() override { return 0; } protected: IBinder* onAsBinder() { return nullptr; } private: - FuzzedDataProvider *fdp; - std::vector<std::shared_ptr<MediaBufferBase>> buffer_bases; - const size_t max_buffer_size; + uint8_t frames_read; + FuzzedDataProvider* fdp; + const size_t min_buffer_size; + const size_t max_buffer_size; + std::vector<uint8_t> buf; }; // This class is simply to expose the destructor @@ -53,32 +55,41 @@ class MediaBufferFuzzImpl : public MediaBuffer { ~MediaBufferFuzzImpl() {} }; -status_t IMediaSourceFuzzImpl::read(MediaBufferBase **buffer, - const MediaSource::ReadOptions *options) { +status_t IMediaSourceFuzzImpl::read(MediaBufferBase** buffer, const MediaSource::ReadOptions*) { Vector<MediaBufferBase*> buffers; - status_t ret = readMultiple(&buffers, 1, options); + status_t ret = readMultiple(&buffers, 1, nullptr); *buffer = buffers.empty() ? nullptr : buffers[0]; return ret; } -status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers, - uint32_t maxNumBuffers, const MediaSource::ReadOptions*) { - uint32_t num_buffers = - fdp->ConsumeIntegralInRange<uint32_t>(0, maxNumBuffers); - for(uint32_t i = 0; i < num_buffers; i++) { - std::vector<uint8_t> buf = fdp->ConsumeBytes<uint8_t>( - fdp->ConsumeIntegralInRange<size_t>(0, max_buffer_size)); +status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers, uint32_t, + const MediaSource::ReadOptions*) { + if (++frames_read == MAX_FRAMES) { + auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size); + buf = fdp->ConsumeBytes<uint8_t>(size); + if (buf.size() < size) { + buf.resize(size, 0); + } + + MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size()); + mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>()); + buffers->push_back(mbb); - std::shared_ptr<MediaBufferBase> mbb( - new MediaBufferFuzzImpl(buf.data(), buf.size())); + return ERROR_END_OF_STREAM; + } - buffer_bases.push_back(mbb); - buffers->push_back(mbb.get()); + auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size); + buf = fdp->ConsumeBytes<uint8_t>(size); + if (buf.size() < size) { + buf.resize(size, 0); } - // STATUS_OK - return 0; + MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size()); + mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>()); + buffers->push_back(mbb); + + return OK; } } // namespace android diff --git a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h index 9f337acc61..de7814e7c1 100644 --- a/media/libstagefright/tests/fuzzers/MediaMimeTypes.h +++ b/media/libstagefright/tests/fuzzers/MediaMimeTypes.h @@ -18,6 +18,7 @@ #define FUZZER_MEDIAMIMETYPES_H_ #include <media/stagefright/foundation/MediaDefs.h> +#include <unordered_map> namespace android { @@ -80,6 +81,15 @@ static const std::vector<const char*> kMimeTypes { MEDIA_MIMETYPE_DATA_TIMED_ID3 }; +static const std::unordered_map<std::string, const char*> decoderToMediaType = { + {"c2.android.vp8.decoder", MEDIA_MIMETYPE_VIDEO_VP8}, + {"c2.android.vp9.decoder", MEDIA_MIMETYPE_VIDEO_VP9}, + {"c2.android.av1.decoder", MEDIA_MIMETYPE_VIDEO_AV1}, + {"c2.android.avc.decoder", MEDIA_MIMETYPE_VIDEO_AVC}, + {"c2.android.hevc.decoder", MEDIA_MIMETYPE_VIDEO_HEVC}, + {"c2.android.mpeg4.decoder", MEDIA_MIMETYPE_VIDEO_MPEG4}, + {"c2.android.h263.decoder", MEDIA_MIMETYPE_VIDEO_H263}}; + } // namespace android #endif // FUZZER_MEDIAMIMETYPES_H_ diff --git a/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 Binary files differnew file mode 100644 index 0000000000..652581f591 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/0ef67b8a074fed50b8875df345ab2e62175c34c9 diff --git a/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc Binary files differnew file mode 100644 index 0000000000..60ca169be9 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/60eb43c963545c0b2676dad3e4c38cfe87136bbc diff --git a/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e Binary files differnew file mode 100644 index 0000000000..c03bcadc61 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/8c7cb9439f81a8e00b651b3658fe24116f37df7e diff --git a/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 Binary files differnew file mode 100644 index 0000000000..52f2d5abf7 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/c624e73c16c59dfbc3c563416cfc962e3c3a96a0 diff --git a/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca Binary files differnew file mode 100644 index 0000000000..83c522f291 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/c6aff0d7ccaf58a1964a6bcc51777bf1786503ca diff --git a/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 Binary files differnew file mode 100644 index 0000000000..62d259b81b --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/ec6bd6069f74a2f6e92442f88efb29288ad6f456 diff --git a/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 Binary files differnew file mode 100644 index 0000000000..db78b75b34 --- /dev/null +++ b/media/libstagefright/tests/fuzzers/corpus/fbf47d9a9173df0a39285c94d89fcbc767d5e774 |