Loading media/libstagefright/tests/fuzzers/Android.bp +9 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,15 @@ cc_defaults { "liblog", "media_permission-aidl-cpp", ], fuzz_config: { componentid: 42195, hotlists: ["4593311"], description: "The fuzzer targets the APIs of libstagefright", vector: "local_no_privileges_required", service_privilege: "constrained", users: "multi_user", fuzzed_code_usage: "shipped", }, } cc_fuzz { Loading media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp +199 −72 Original line number Diff line number Diff line Loading @@ -13,93 +13,220 @@ * See the License for the specific language governing permissions and * limitations under the License. */ // Authors: corbin.souffrant@leviathansecurity.com // dylan.katz@leviathansecurity.com #include <MediaMuxerFuzzer.h> #include <cutils/ashmem.h> #include <fuzzer/FuzzedDataProvider.h> #include <media/stagefright/MediaMuxer.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/foundation/MediaDefs.h> namespace android { const uint8_t kMinSize = 0; const uint8_t kMinTrackCount = 0; // Can't seem to get setBuffer or setString working. It always segfaults on a // null pointer read or memleaks. So that functionality is missing. void createMessage(AMessage *msg, FuzzedDataProvider *fdp) { size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 32); while (fdp->remaining_bytes() > 0 && count > 0) { uint8_t function_id = fdp->ConsumeIntegralInRange<uint8_t>(0, amessage_setvals.size() - 1); amessage_setvals[function_id](msg, fdp); count--; enum kBufferFlags { BUFFER_FLAG_SYNCFRAME = 1, BUFFER_FLAG_CODECCONFIG = 2, BUFFER_FLAG_EOS = 4 }; constexpr char kMuxerFile[] = "MediaMuxer"; const std::string kAudioMimeTypes[] = { 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_MPEGH_MHA1, MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1, MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3, MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4, MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3, MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4, 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_AUDIO_DTS, MEDIA_MIMETYPE_AUDIO_DTS_HD, MEDIA_MIMETYPE_AUDIO_DTS_HD_MA, MEDIA_MIMETYPE_AUDIO_DTS_UHD, MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1, MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2, MEDIA_MIMETYPE_AUDIO_EVRC, MEDIA_MIMETYPE_AUDIO_EVRCB, MEDIA_MIMETYPE_AUDIO_EVRCWB, MEDIA_MIMETYPE_AUDIO_EVRCNW, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS, MEDIA_MIMETYPE_AUDIO_APTX, MEDIA_MIMETYPE_AUDIO_DRA, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_1_0, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_0, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_1, MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD, MEDIA_MIMETYPE_AUDIO_AAC_MP4, MEDIA_MIMETYPE_AUDIO_AAC_MAIN, MEDIA_MIMETYPE_AUDIO_AAC_LC, MEDIA_MIMETYPE_AUDIO_AAC_SSR, MEDIA_MIMETYPE_AUDIO_AAC_LTP, MEDIA_MIMETYPE_AUDIO_AAC_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE, MEDIA_MIMETYPE_AUDIO_AAC_ERLC, MEDIA_MIMETYPE_AUDIO_AAC_LD, MEDIA_MIMETYPE_AUDIO_AAC_HE_V2, MEDIA_MIMETYPE_AUDIO_AAC_ELD, MEDIA_MIMETYPE_AUDIO_AAC_XHE, MEDIA_MIMETYPE_AUDIO_AAC_ADIF, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE, MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2, MEDIA_MIMETYPE_AUDIO_IEC61937, MEDIA_MIMETYPE_AUDIO_IEC60958, }; const std::string kVideoMimeTypes[] = { 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, }; void getSampleAudioFormat(FuzzedDataProvider& fdp, AMessage* format) { std::string mimeType = fdp.PickValueInArray(kAudioMimeTypes); format->setString("mime", mimeType.c_str(), mimeType.length()); format->setInt32("sample-rate", fdp.ConsumeIntegral<int32_t>()); format->setInt32("channel-count", fdp.ConsumeIntegral<int32_t>()); } void getSampleVideoFormat(FuzzedDataProvider& fdp, AMessage* format) { std::string mimeType = fdp.PickValueInArray(kVideoMimeTypes); format->setString("mime", mimeType.c_str(), mimeType.length()); format->setInt32("height", fdp.ConsumeIntegral<int32_t>()); format->setInt32("width", fdp.ConsumeIntegral<int32_t>()); format->setInt32("time-lapse-fps", fdp.ConsumeIntegral<int32_t>()); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp = FuzzedDataProvider(data, size); FuzzedDataProvider fdp(data, size); size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size); int fd = ashmem_create_region("mediamuxer_fuzz_region", data_size); if (fd < 0) // memfd_create() creates an anonymous file and returns a file // descriptor that refers to it. MFD_ALLOW_SEALING allows sealing // operations on this file. int32_t fd = memfd_create(kMuxerFile, MFD_ALLOW_SEALING); if (fd == -1) { ALOGE("memfd_create failed: %s", strerror(errno)); return 0; } uint8_t *sh_data = static_cast<uint8_t *>( mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); if (sh_data == MAP_FAILED) return 0; auto outputFormat = (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>( MediaMuxer::OutputFormat::OUTPUT_FORMAT_MPEG_4, MediaMuxer::OutputFormat::OUTPUT_FORMAT_LIST_END); MediaMuxer::OutputFormat format = (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4); sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, format); sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, outputFormat); if (mMuxer == nullptr) { close(fd); return 0; } while (fdp.remaining_bytes() > 1) { switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) { case 0: { // For some reason it only likes mp4s here... if (format == 1 || format == 4) break; sp<AMessage> a_format(new AMessage); createMessage(a_format.get(), &fdp); mMuxer->addTrack(a_format); break; // Used to consume a maximum of 80% of the data to send buffer data to writeSampleData(). // This ensures that we don't completely exhaust data and use the rest 20% for fuzzing // of APIs. const size_t kMaxSize = (size * 80) / 100; while (fdp.remaining_bytes()) { auto invokeMediaMuxerAPI = fdp.PickValueInArray<const std::function<void()>>({ [&]() { // Using 'return' here due to a timeout bug present in OGGWriter.cpp // (b/310316183). if (outputFormat == MediaMuxer::OutputFormat::OUTPUT_FORMAT_OGG) { return; } case 1: { mMuxer->start(); break; sp<AMessage> format = sp<AMessage>::make(); fdp.ConsumeBool() ? getSampleAudioFormat(fdp, format.get()) : getSampleVideoFormat(fdp, format.get()); mMuxer->addTrack(fdp.ConsumeBool() ? format : nullptr); }, [&]() { mMuxer->setLocation(fdp.ConsumeIntegral<int32_t>() /* latitude */, fdp.ConsumeIntegral<int32_t>() /* longitude */); }, [&]() { mMuxer->setOrientationHint(fdp.ConsumeIntegral<int32_t>() /* degrees */); }, [&]() { mMuxer->start(); }, [&]() { std::vector<uint8_t> sample = fdp.ConsumeBytes<uint8_t>( fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); sp<ABuffer> buffer = sp<ABuffer>::make(sample.data(), sample.size()); size_t offset = fdp.ConsumeIntegralInRange<size_t>(kMinSize, sample.size()); size_t length = fdp.ConsumeIntegralInRange<size_t>(kMinSize, buffer->size() - offset); buffer->setRange(offset, length); sp<AMessage> meta = buffer->meta(); meta->setInt64("sample-file-offset", fdp.ConsumeIntegral<int64_t>()); meta->setInt64("last-sample-index-in-chunk", fdp.ConsumeIntegral<int64_t>()); uint32_t flags = 0; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_SYNCFRAME; } case 2: { int degrees = fdp.ConsumeIntegral<int>(); mMuxer->setOrientationHint(degrees); break; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_CODECCONFIG; } case 3: { int latitude = fdp.ConsumeIntegral<int>(); int longitude = fdp.ConsumeIntegral<int>(); mMuxer->setLocation(latitude, longitude); break; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_EOS; } case 4: { size_t buf_size = fdp.ConsumeIntegralInRange<size_t>(0, data_size); sp<ABuffer> a_buffer(new ABuffer(buf_size)); size_t trackIndex = fdp.ConsumeIntegral<size_t>(); size_t trackIndex = fdp.ConsumeBool() ? fdp.ConsumeIntegralInRange<size_t>( kMinTrackCount, mMuxer->getTrackCount()) : fdp.ConsumeIntegral<size_t>(); int64_t timeUs = fdp.ConsumeIntegral<int64_t>(); uint32_t flags = fdp.ConsumeIntegral<uint32_t>(); mMuxer->writeSampleData(a_buffer, trackIndex, timeUs, flags); } } } mMuxer->writeSampleData(fdp.ConsumeBool() ? buffer : nullptr, trackIndex, timeUs, flags); }, [&]() { mMuxer->getTrackFormat( fdp.ConsumeBool() ? fdp.ConsumeIntegralInRange<size_t>( kMinTrackCount, mMuxer->getTrackCount()) : fdp.ConsumeIntegral<size_t>() /* idx */); }, [&]() { mMuxer->stop(); }, }); if (fdp.ConsumeBool()) mMuxer->stop(); invokeMediaMuxerAPI(); } munmap(sh_data, data_size); close(fd); return 0; } Loading media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.hdeleted 100644 → 0 +0 −109 Original line number Diff line number Diff line /* * Copyright 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. */ // Authors: corbin.souffrant@leviathansecurity.com // dylan.katz@leviathansecurity.com #pragma once #include <fuzzer/FuzzedDataProvider.h> #include <media/stagefright/foundation/AMessage.h> namespace android { // Mappings vectors are the list of attributes that the MediaMuxer // class looks for in the message. static std::vector<const char *> floatMappings{ "capture-rate", "time-lapse-fps", "frame-rate", }; static std::vector<const char *> int64Mappings{ "exif-offset", "exif-size", "target-time", "thumbnail-time", "timeUs", "durationUs", }; static std::vector<const char *> int32Mappings{"loop", "time-scale", "crypto-mode", "crypto-default-iv-size", "crypto-encrypted-byte-block", "crypto-skip-byte-block", "frame-count", "max-bitrate", "pcm-big-endian", "temporal-layer-count", "temporal-layer-id", "thumbnail-width", "thumbnail-height", "track-id", "valid-samples", "color-format", "ca-system-id", "is-sync-frame", "bitrate", "max-bitrate", "width", "height", "sar-width", "sar-height", "display-width", "display-height", "is-default", "tile-width", "tile-height", "grid-rows", "grid-cols", "rotation-degrees", "channel-count", "sample-rate", "bits-per-sample", "channel-mask", "encoder-delay", "encoder-padding", "is-adts", "frame-rate", "max-height", "max-width", "max-input-size", "haptic-channel-count", "pcm-encoding", "aac-profile"}; static const std::vector<std::function<void(AMessage *, FuzzedDataProvider *)>> amessage_setvals = { [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setRect("crop", fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setFloat(floatMappings[fdp->ConsumeIntegralInRange<size_t>( 0, floatMappings.size() - 1)], fdp->ConsumeFloatingPoint<float>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setInt64(int64Mappings[fdp->ConsumeIntegralInRange<size_t>( 0, int64Mappings.size() - 1)], fdp->ConsumeIntegral<int64_t>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setInt32(int32Mappings[fdp->ConsumeIntegralInRange<size_t>( 0, int32Mappings.size() - 1)], fdp->ConsumeIntegral<int32_t>()); }}; } // namespace android Loading
media/libstagefright/tests/fuzzers/Android.bp +9 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,15 @@ cc_defaults { "liblog", "media_permission-aidl-cpp", ], fuzz_config: { componentid: 42195, hotlists: ["4593311"], description: "The fuzzer targets the APIs of libstagefright", vector: "local_no_privileges_required", service_privilege: "constrained", users: "multi_user", fuzzed_code_usage: "shipped", }, } cc_fuzz { Loading
media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp +199 −72 Original line number Diff line number Diff line Loading @@ -13,93 +13,220 @@ * See the License for the specific language governing permissions and * limitations under the License. */ // Authors: corbin.souffrant@leviathansecurity.com // dylan.katz@leviathansecurity.com #include <MediaMuxerFuzzer.h> #include <cutils/ashmem.h> #include <fuzzer/FuzzedDataProvider.h> #include <media/stagefright/MediaMuxer.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/foundation/MediaDefs.h> namespace android { const uint8_t kMinSize = 0; const uint8_t kMinTrackCount = 0; // Can't seem to get setBuffer or setString working. It always segfaults on a // null pointer read or memleaks. So that functionality is missing. void createMessage(AMessage *msg, FuzzedDataProvider *fdp) { size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 32); while (fdp->remaining_bytes() > 0 && count > 0) { uint8_t function_id = fdp->ConsumeIntegralInRange<uint8_t>(0, amessage_setvals.size() - 1); amessage_setvals[function_id](msg, fdp); count--; enum kBufferFlags { BUFFER_FLAG_SYNCFRAME = 1, BUFFER_FLAG_CODECCONFIG = 2, BUFFER_FLAG_EOS = 4 }; constexpr char kMuxerFile[] = "MediaMuxer"; const std::string kAudioMimeTypes[] = { 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_MPEGH_MHA1, MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1, MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3, MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4, MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3, MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4, 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_AUDIO_DTS, MEDIA_MIMETYPE_AUDIO_DTS_HD, MEDIA_MIMETYPE_AUDIO_DTS_HD_MA, MEDIA_MIMETYPE_AUDIO_DTS_UHD, MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1, MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2, MEDIA_MIMETYPE_AUDIO_EVRC, MEDIA_MIMETYPE_AUDIO_EVRCB, MEDIA_MIMETYPE_AUDIO_EVRCWB, MEDIA_MIMETYPE_AUDIO_EVRCNW, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS, MEDIA_MIMETYPE_AUDIO_APTX, MEDIA_MIMETYPE_AUDIO_DRA, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_1_0, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_0, MEDIA_MIMETYPE_AUDIO_DOLBY_MAT_2_1, MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD, MEDIA_MIMETYPE_AUDIO_AAC_MP4, MEDIA_MIMETYPE_AUDIO_AAC_MAIN, MEDIA_MIMETYPE_AUDIO_AAC_LC, MEDIA_MIMETYPE_AUDIO_AAC_SSR, MEDIA_MIMETYPE_AUDIO_AAC_LTP, MEDIA_MIMETYPE_AUDIO_AAC_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE, MEDIA_MIMETYPE_AUDIO_AAC_ERLC, MEDIA_MIMETYPE_AUDIO_AAC_LD, MEDIA_MIMETYPE_AUDIO_AAC_HE_V2, MEDIA_MIMETYPE_AUDIO_AAC_ELD, MEDIA_MIMETYPE_AUDIO_AAC_XHE, MEDIA_MIMETYPE_AUDIO_AAC_ADIF, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD, MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE, MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1, MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2, MEDIA_MIMETYPE_AUDIO_IEC61937, MEDIA_MIMETYPE_AUDIO_IEC60958, }; const std::string kVideoMimeTypes[] = { 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, }; void getSampleAudioFormat(FuzzedDataProvider& fdp, AMessage* format) { std::string mimeType = fdp.PickValueInArray(kAudioMimeTypes); format->setString("mime", mimeType.c_str(), mimeType.length()); format->setInt32("sample-rate", fdp.ConsumeIntegral<int32_t>()); format->setInt32("channel-count", fdp.ConsumeIntegral<int32_t>()); } void getSampleVideoFormat(FuzzedDataProvider& fdp, AMessage* format) { std::string mimeType = fdp.PickValueInArray(kVideoMimeTypes); format->setString("mime", mimeType.c_str(), mimeType.length()); format->setInt32("height", fdp.ConsumeIntegral<int32_t>()); format->setInt32("width", fdp.ConsumeIntegral<int32_t>()); format->setInt32("time-lapse-fps", fdp.ConsumeIntegral<int32_t>()); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp = FuzzedDataProvider(data, size); FuzzedDataProvider fdp(data, size); size_t data_size = fdp.ConsumeIntegralInRange<size_t>(0, size); int fd = ashmem_create_region("mediamuxer_fuzz_region", data_size); if (fd < 0) // memfd_create() creates an anonymous file and returns a file // descriptor that refers to it. MFD_ALLOW_SEALING allows sealing // operations on this file. int32_t fd = memfd_create(kMuxerFile, MFD_ALLOW_SEALING); if (fd == -1) { ALOGE("memfd_create failed: %s", strerror(errno)); return 0; } uint8_t *sh_data = static_cast<uint8_t *>( mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); if (sh_data == MAP_FAILED) return 0; auto outputFormat = (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>( MediaMuxer::OutputFormat::OUTPUT_FORMAT_MPEG_4, MediaMuxer::OutputFormat::OUTPUT_FORMAT_LIST_END); MediaMuxer::OutputFormat format = (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4); sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, format); sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, outputFormat); if (mMuxer == nullptr) { close(fd); return 0; } while (fdp.remaining_bytes() > 1) { switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) { case 0: { // For some reason it only likes mp4s here... if (format == 1 || format == 4) break; sp<AMessage> a_format(new AMessage); createMessage(a_format.get(), &fdp); mMuxer->addTrack(a_format); break; // Used to consume a maximum of 80% of the data to send buffer data to writeSampleData(). // This ensures that we don't completely exhaust data and use the rest 20% for fuzzing // of APIs. const size_t kMaxSize = (size * 80) / 100; while (fdp.remaining_bytes()) { auto invokeMediaMuxerAPI = fdp.PickValueInArray<const std::function<void()>>({ [&]() { // Using 'return' here due to a timeout bug present in OGGWriter.cpp // (b/310316183). if (outputFormat == MediaMuxer::OutputFormat::OUTPUT_FORMAT_OGG) { return; } case 1: { mMuxer->start(); break; sp<AMessage> format = sp<AMessage>::make(); fdp.ConsumeBool() ? getSampleAudioFormat(fdp, format.get()) : getSampleVideoFormat(fdp, format.get()); mMuxer->addTrack(fdp.ConsumeBool() ? format : nullptr); }, [&]() { mMuxer->setLocation(fdp.ConsumeIntegral<int32_t>() /* latitude */, fdp.ConsumeIntegral<int32_t>() /* longitude */); }, [&]() { mMuxer->setOrientationHint(fdp.ConsumeIntegral<int32_t>() /* degrees */); }, [&]() { mMuxer->start(); }, [&]() { std::vector<uint8_t> sample = fdp.ConsumeBytes<uint8_t>( fdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); sp<ABuffer> buffer = sp<ABuffer>::make(sample.data(), sample.size()); size_t offset = fdp.ConsumeIntegralInRange<size_t>(kMinSize, sample.size()); size_t length = fdp.ConsumeIntegralInRange<size_t>(kMinSize, buffer->size() - offset); buffer->setRange(offset, length); sp<AMessage> meta = buffer->meta(); meta->setInt64("sample-file-offset", fdp.ConsumeIntegral<int64_t>()); meta->setInt64("last-sample-index-in-chunk", fdp.ConsumeIntegral<int64_t>()); uint32_t flags = 0; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_SYNCFRAME; } case 2: { int degrees = fdp.ConsumeIntegral<int>(); mMuxer->setOrientationHint(degrees); break; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_CODECCONFIG; } case 3: { int latitude = fdp.ConsumeIntegral<int>(); int longitude = fdp.ConsumeIntegral<int>(); mMuxer->setLocation(latitude, longitude); break; if (fdp.ConsumeBool()) { flags |= kBufferFlags::BUFFER_FLAG_EOS; } case 4: { size_t buf_size = fdp.ConsumeIntegralInRange<size_t>(0, data_size); sp<ABuffer> a_buffer(new ABuffer(buf_size)); size_t trackIndex = fdp.ConsumeIntegral<size_t>(); size_t trackIndex = fdp.ConsumeBool() ? fdp.ConsumeIntegralInRange<size_t>( kMinTrackCount, mMuxer->getTrackCount()) : fdp.ConsumeIntegral<size_t>(); int64_t timeUs = fdp.ConsumeIntegral<int64_t>(); uint32_t flags = fdp.ConsumeIntegral<uint32_t>(); mMuxer->writeSampleData(a_buffer, trackIndex, timeUs, flags); } } } mMuxer->writeSampleData(fdp.ConsumeBool() ? buffer : nullptr, trackIndex, timeUs, flags); }, [&]() { mMuxer->getTrackFormat( fdp.ConsumeBool() ? fdp.ConsumeIntegralInRange<size_t>( kMinTrackCount, mMuxer->getTrackCount()) : fdp.ConsumeIntegral<size_t>() /* idx */); }, [&]() { mMuxer->stop(); }, }); if (fdp.ConsumeBool()) mMuxer->stop(); invokeMediaMuxerAPI(); } munmap(sh_data, data_size); close(fd); return 0; } Loading
media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.hdeleted 100644 → 0 +0 −109 Original line number Diff line number Diff line /* * Copyright 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. */ // Authors: corbin.souffrant@leviathansecurity.com // dylan.katz@leviathansecurity.com #pragma once #include <fuzzer/FuzzedDataProvider.h> #include <media/stagefright/foundation/AMessage.h> namespace android { // Mappings vectors are the list of attributes that the MediaMuxer // class looks for in the message. static std::vector<const char *> floatMappings{ "capture-rate", "time-lapse-fps", "frame-rate", }; static std::vector<const char *> int64Mappings{ "exif-offset", "exif-size", "target-time", "thumbnail-time", "timeUs", "durationUs", }; static std::vector<const char *> int32Mappings{"loop", "time-scale", "crypto-mode", "crypto-default-iv-size", "crypto-encrypted-byte-block", "crypto-skip-byte-block", "frame-count", "max-bitrate", "pcm-big-endian", "temporal-layer-count", "temporal-layer-id", "thumbnail-width", "thumbnail-height", "track-id", "valid-samples", "color-format", "ca-system-id", "is-sync-frame", "bitrate", "max-bitrate", "width", "height", "sar-width", "sar-height", "display-width", "display-height", "is-default", "tile-width", "tile-height", "grid-rows", "grid-cols", "rotation-degrees", "channel-count", "sample-rate", "bits-per-sample", "channel-mask", "encoder-delay", "encoder-padding", "is-adts", "frame-rate", "max-height", "max-width", "max-input-size", "haptic-channel-count", "pcm-encoding", "aac-profile"}; static const std::vector<std::function<void(AMessage *, FuzzedDataProvider *)>> amessage_setvals = { [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setRect("crop", fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setFloat(floatMappings[fdp->ConsumeIntegralInRange<size_t>( 0, floatMappings.size() - 1)], fdp->ConsumeFloatingPoint<float>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setInt64(int64Mappings[fdp->ConsumeIntegralInRange<size_t>( 0, int64Mappings.size() - 1)], fdp->ConsumeIntegral<int64_t>()); }, [](AMessage *msg, FuzzedDataProvider *fdp) -> void { msg->setInt32(int32Mappings[fdp->ConsumeIntegralInRange<size_t>( 0, int32Mappings.size() - 1)], fdp->ConsumeIntegral<int32_t>()); }}; } // namespace android