Merge "Refactored libstagefright_writer_fuzzer" into main
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
index 9f46a74..b29429a 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -21,105 +21,256 @@
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OggWriter.h>
-
-#include "MediaMimeTypes.h"
-
#include <webm/WebmWriter.h>
namespace android {
-std::string genMimeType(FuzzedDataProvider *dataProvider) {
- uint8_t idx = dataProvider->ConsumeIntegralInRange<uint8_t>(0, kMimeTypes.size() - 1);
- return std::string(kMimeTypes[idx]);
-}
-sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, std::string mimeType,
- uint16_t maxDataAmount) {
- uint32_t dataBlobSize = dataProvider->ConsumeIntegralInRange<uint16_t>(0, maxDataAmount);
- std::vector<uint8_t> data = dataProvider->ConsumeBytes<uint8_t>(dataBlobSize);
- // data:[<mediatype>][;base64],<data>
- std::string uri("data:");
- uri += mimeType;
- // Currently libstagefright only accepts base64 uris
- uri += ";base64,";
- android::AString out;
- android::encodeBase64(data.data(), data.size(), &out);
- uri += out.c_str();
-
- sp<DataSource> source =
- DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri.c_str());
-
- if (source == NULL) {
- return NULL;
- }
-
- return MediaExtractorFactory::Create(source);
-}
-
-sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize) {
- std::string mime = genMimeType(dataProvider);
- sp<IMediaExtractor> extractor = genMediaExtractor(dataProvider, mime, maxMediaBlobSize);
-
- if (extractor == NULL) {
- return NULL;
- }
-
- for (size_t i = 0; i < extractor->countTracks(); ++i) {
- sp<MetaData> meta = extractor->getTrackMetaData(i);
-
- std::string trackMime = dataProvider->PickValueInArray(kTestedMimeTypes);
- if (!strcasecmp(mime.c_str(), trackMime.c_str())) {
- sp<IMediaSource> track = extractor->getTrack(i);
- if (track == NULL) {
- return NULL;
- }
- return new CallbackMediaSource(track);
- }
- }
-
- return NULL;
-}
-
-sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> fileMeta) {
+sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> writerMeta,
+ FuzzedDataProvider* fdp) {
sp<MediaWriter> writer;
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyRealTimeRecording, fdp->ConsumeBool());
+ }
+
switch (writerType) {
- case OGG:
- writer = new OggWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
- break;
case AAC:
- writer = new AACWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ writer = sp<AACWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ }
break;
case AAC_ADTS:
- writer = new AACWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
- break;
- case WEBM:
- writer = new WebmWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
- break;
- case MPEG4:
- writer = new MPEG4Writer(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ writer = sp<AACWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+ }
break;
case AMR_NB:
- writer = new AMRWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ writer = sp<AMRWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ }
break;
case AMR_WB:
- writer = new AMRWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ writer = sp<AMRWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ }
break;
case MPEG2TS:
- writer = new MPEG2TSWriter(fd);
- fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ writer = sp<MPEG2TSWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ }
break;
- default:
- return nullptr;
+ case MPEG4:
+ writer = sp<MPEG4Writer>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ } else if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_HEIF);
+ } else if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_THREE_GPP);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKey2ByteNalLength, fdp->ConsumeBool());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyTimeScale,
+ fdp->ConsumeIntegralInRange<int32_t>(600, 96000));
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKey4BitTrackIds, fdp->ConsumeBool());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt64(kKeyTrackTimeStatus, fdp->ConsumeIntegral<int64_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyRotation, fdp->ConsumeIntegralInRange<uint8_t>(0, 3) * 90);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt64(kKeyTime, fdp->ConsumeIntegral<int64_t>());
+ }
+ break;
+ case OGG:
+ writer = sp<OggWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ }
+ break;
+ case WEBM:
+ writer = sp<WebmWriter>::make(fd);
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ }
+
+ if (fdp->ConsumeBool()) {
+ writerMeta->setInt32(kKeyTimeScale,
+ fdp->ConsumeIntegralInRange<int32_t>(600, 96000));
+ }
+ break;
}
- if (writer != nullptr) {
- fileMeta->setInt32(kKeyRealTimeRecording, false);
- }
+
return writer;
}
+
+sp<FuzzSource> createSource(StandardWriters writerType, FuzzedDataProvider* fdp) {
+ sp<MetaData> meta = sp<MetaData>::make();
+
+ switch (writerType) {
+ case AAC:
+ case AAC_ADTS:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegralInRange<uint8_t>(1, 7));
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyAACProfile, fdp->ConsumeIntegral<int32_t>());
+ }
+ break;
+ case AMR_NB:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
+ meta->setInt32(kKeyChannelCount, 1);
+ meta->setInt32(kKeySampleRate, 8000);
+ break;
+ case AMR_WB:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+ meta->setInt32(kKeyChannelCount, 1);
+ meta->setInt32(kKeySampleRate, 16000);
+ break;
+ case MPEG2TS:
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+ }
+ break;
+ case MPEG4: {
+ auto mime = fdp->PickValueInArray<std::string>(kMpeg4MimeTypes);
+ meta->setCString(kKeyMIMEType, mime.c_str());
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyBackgroundMode, fdp->ConsumeBool());
+ }
+
+ if (!strncasecmp(mime.c_str(), "audio/", 6)) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+
+ } else {
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyDisplayWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyDisplayHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTileWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTileHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyGridRows, fdp->ConsumeIntegral<uint8_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyGridCols, fdp->ConsumeIntegral<uint8_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTemporalLayerCount, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySARWidth, fdp->ConsumeIntegral<uint16_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySARHeight, fdp->ConsumeIntegral<uint16_t>());
+ }
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyBitRate, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyMaxBitRate, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyTrackIsDefault, fdp->ConsumeBool());
+ }
+ break;
+ }
+ case OGG:
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ }
+ break;
+ case WEBM:
+ if (fdp->ConsumeBool()) {
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
+ }
+
+ if (fdp->ConsumeBool()) {
+ // The +1s ensure a minimum height and width of 1.
+ meta->setInt32(kKeyWidth, fdp->ConsumeIntegral<uint16_t>() + 1);
+ meta->setInt32(kKeyHeight, fdp->ConsumeIntegral<uint16_t>() + 1);
+ }
+ } else {
+ if (fdp->ConsumeBool()) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+ } else {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
+ }
+
+ if (fdp->ConsumeBool()) {
+ meta->setInt32(kKeyChannelCount, fdp->ConsumeIntegral<int32_t>());
+ }
+ meta->setInt32(kKeySampleRate, fdp->PickValueInArray<uint32_t>(kSampleRateTable));
+ }
+
+ break;
+ }
+
+ return sp<FuzzSource>::make(meta, fdp);
+}
} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
index 6856ac0..ad1218b 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -15,20 +15,52 @@
*/
#pragma once
-#include <datasource/DataSourceFactory.h>
+
#include <fuzzer/FuzzedDataProvider.h>
-#include <android/IMediaExtractor.h>
-#include <media/IMediaHTTPService.h>
-#include <media/mediarecorder.h>
-#include <media/stagefright/CallbackMediaSource.h>
+
+#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MediaWriter.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/foundation/base64.h>
-#include <utils/StrongPointer.h>
namespace android {
+class FuzzSource : public MediaSource {
+ public:
+ FuzzSource(sp<MetaData> meta, FuzzedDataProvider* fdp) : mMetaData(meta), mFdp(fdp) {}
+
+ status_t start(MetaData*) { return OK; }
+
+ virtual status_t stop() { return OK; }
+
+ status_t read(MediaBufferBase** buffer, const ReadOptions*) {
+ // Ensuring that mBuffer has at least two bytes to avoid check failure
+ // in MPEG2TSWriter::SourceInfo::onMessageReceived().
+ if (mFdp->remaining_bytes() > 2) {
+ auto size = mFdp->ConsumeIntegralInRange<uint8_t>(2, INT8_MAX);
+ mBuffer = mFdp->ConsumeBytes<uint8_t>(size);
+ MediaBufferBase* mbb = new MediaBuffer(mBuffer.data(), mBuffer.size());
+
+ size_t length = mFdp->ConsumeIntegralInRange<size_t>(2, mbb->size());
+ size_t offset = mFdp->ConsumeIntegralInRange<size_t>(0, mbb->size() - length);
+ mbb->set_range(offset, length);
+
+ mbb->meta_data().setInt32(kKeyIsEndOfStream, mFdp->ConsumeBool());
+ mbb->meta_data().setInt64(kKeyTime, mFdp->ConsumeIntegral<uint32_t>() / 2);
+ *buffer = mbb;
+
+ return OK;
+ }
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ sp<MetaData> getFormat() { return mMetaData; }
+
+ private:
+ sp<MetaData> mMetaData = nullptr;
+ FuzzedDataProvider* mFdp = nullptr;
+ std::vector<uint8_t> mBuffer;
+};
+
enum StandardWriters {
OGG,
AAC,
@@ -42,54 +74,22 @@
kMaxValue = MPEG2TS,
};
-static std::string kTestedMimeTypes[] = {"audio/3gpp",
- "audio/amr-wb",
- "audio/vorbis",
- "audio/opus",
- "audio/mp4a-latm",
- "audio/mpeg",
- "audio/mpeg-L1",
- "audio/mpeg-L2",
- "audio/midi",
- "audio/qcelp",
- "audio/g711-alaw",
- "audio/g711-mlaw",
- "audio/flac",
- "audio/aac-adts",
- "audio/gsm",
- "audio/ac3",
- "audio/eac3",
- "audio/eac3-joc",
- "audio/ac4",
- "audio/scrambled",
- "audio/alac",
- "audio/x-ms-wma",
- "audio/x-adpcm-ms",
- "audio/x-adpcm-dvi-ima",
- "video/avc",
- "video/hevc",
- "video/mp4v-es",
- "video/3gpp",
- "video/x-vnd.on2.vp8",
- "video/x-vnd.on2.vp9",
- "video/av01",
- "video/mpeg2",
- "video/dolby-vision",
- "video/scrambled",
- "video/divx",
- "video/divx3",
- "video/xvid",
- "video/x-motion-jpeg",
- "text/3gpp-tt",
- "application/x-subrip",
- "text/vtt",
- "text/cea-608",
- "text/cea-708",
- "application/x-id3v4"};
+static const uint32_t kSampleRateTable[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000,
+};
+static const std::string kMpeg4MimeTypes[] = {
+ MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, MEDIA_MIMETYPE_IMAGE_AVIF,
-std::string genMimeType(FuzzedDataProvider *dataProvider);
-sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
-sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
+ MEDIA_MIMETYPE_VIDEO_AV1, MEDIA_MIMETYPE_VIDEO_AVC,
+ MEDIA_MIMETYPE_VIDEO_HEVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
-sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> fileMeta);
+ MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_AAC,
+};
+
+sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> writerMeta,
+ FuzzedDataProvider* fdp);
+
+sp<FuzzSource> createSource(StandardWriters writerType, FuzzedDataProvider* fdp);
} // namespace android
diff --git a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
index 97d1160..cd0a866 100644
--- a/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/WriterFuzzer.cpp
@@ -13,216 +13,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// Authors: corbin.souffrant@leviathansecurity.com
-// dylan.katz@leviathansecurity.com
-
-#include <android-base/file.h>
-#include <android/content/AttributionSourceState.h>
-#include <ctype.h>
-#include <media/mediarecorder.h>
-#include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <stdlib.h>
-#include <utils/StrongPointer.h>
-#include <utils/Vector.h>
-
-#include <functional>
-#include <string>
#include "FuzzerMediaUtility.h"
-#include "fuzzer/FuzzedDataProvider.h"
-
-static constexpr uint16_t kMaxOperations = 5000;
-static constexpr uint8_t kMaxPackageNameLen = 50;
-// For other strings in mpeg we want a higher limit.
-static constexpr uint16_t kMaxMPEGStrLen = 1000;
-static constexpr uint16_t kMaxMediaBlobSize = 1000;
namespace android {
-using android::content::AttributionSourceState;
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp(data, size);
-std::string getFourCC(FuzzedDataProvider *fdp) {
- std::string fourCC = fdp->ConsumeRandomLengthString(4);
- // Replace any existing nulls
- for (size_t pos = 0; pos < fourCC.length(); pos++) {
- if (fourCC.at(pos) == '\0') {
- fourCC.replace(pos, 1, "a");
- }
+ // 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("WriterFuzzer", MFD_ALLOW_SEALING);
+ if (fd == -1) {
+ ALOGE("memfd_create() failed: %s", strerror(errno));
+ return 0;
}
- // If our string is too short, fill the remainder with "a"s.
- while (fourCC.length() < 4) {
- fourCC += 'a';
- }
- return fourCC;
-}
+ StandardWriters writerType = fdp.ConsumeEnum<StandardWriters>();
+ sp<MetaData> writerMeta = sp<MetaData>::make();
-typedef std::vector<std::function<void(FuzzedDataProvider*,
- sp<MediaWriter>, sp<MetaData>, int tmpFileFd)>> OperationVec;
-typedef std::vector<std::function<void(FuzzedDataProvider*, MPEG4Writer*)>> MPEG4OperationVec;
-static const OperationVec operations = {
- [](FuzzedDataProvider*, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->pause();
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
- bool valid_fd = dataProvider->ConsumeBool();
- int fd = -1;
- if (valid_fd) {
- fd = tmpFd;
- }
- // Args don't seem to be used
- Vector<String16> args;
- mediaWriter->dump(fd, args);
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int tmpFd) {
- bool valid_fd = dataProvider->ConsumeBool();
- int fd = -1;
- if (valid_fd) {
- fd = tmpFd;
- }
- mediaWriter->setNextFd(fd);
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setCaptureRate(dataProvider->ConsumeFloatingPoint<float>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setStartTimeOffsetMs(dataProvider->ConsumeIntegral<int>());
-
- // Likely won't do much, but might as well as do a quick check
- // while we're here.
- mediaWriter->getStartTimeOffsetMs();
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
- [](FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter, sp<MetaData>, int) {
- mediaWriter->setMaxFileDuration(dataProvider->ConsumeIntegral<int64_t>());
- },
-};
-
-static const MPEG4OperationVec mpeg4Operations = {
- [](FuzzedDataProvider*, MPEG4Writer *mediaWriter) { mediaWriter->notifyApproachingLimit(); },
- // Lower level write methods.
- // High-level startBox/endBox/etc are all called elsewhere,
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint8_t val = dataProvider->ConsumeIntegral<uint8_t>();
- mediaWriter->writeInt8(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint16_t val = dataProvider->ConsumeIntegral<uint16_t>();
- mediaWriter->writeInt16(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t val = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->writeInt32(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint64_t val = dataProvider->ConsumeIntegral<uint64_t>();
- mediaWriter->writeInt64(val);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- std::string strVal = dataProvider->ConsumeRandomLengthString(kMaxMPEGStrLen);
- mediaWriter->writeCString(strVal.c_str());
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- std::string fourCC = getFourCC(dataProvider);
- mediaWriter->writeFourcc(fourCC.c_str());
- },
-
- // Misc setters
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t layers = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->setTemporalLayerCount(layers);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- uint32_t duration = dataProvider->ConsumeIntegral<uint32_t>();
- mediaWriter->setInterleaveDuration(duration);
- },
- [](FuzzedDataProvider *dataProvider, MPEG4Writer *mediaWriter) {
- int lat = dataProvider->ConsumeIntegral<int>();
- int lon = dataProvider->ConsumeIntegral<int>();
- mediaWriter->setGeoData(lat, lon);
- },
-};
-
-// Not all writers can always add new sources, so we'll need additional checks.
-void addSource(FuzzedDataProvider *dataProvider, sp<MediaWriter> mediaWriter) {
- sp<MediaSource> mediaSource = genMediaSource(dataProvider, kMaxMediaBlobSize);
- if (mediaSource == NULL) {
- // There's a static check preventing NULLs in addSource.
- return;
- }
- mediaWriter->addSource(mediaSource);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider dataProvider(data, size);
- TemporaryFile tf;
- sp<MetaData> fileMeta = new MetaData;
- StandardWriters writerType = dataProvider.ConsumeEnum<StandardWriters>();
- sp<MediaWriter> writer = createWriter(tf.fd, writerType, fileMeta);
-
- AttributionSourceState attributionSource;
- attributionSource.packageName = dataProvider.ConsumeRandomLengthString(kMaxPackageNameLen);
- attributionSource.uid = dataProvider.ConsumeIntegral<int32_t>();
- attributionSource.pid = dataProvider.ConsumeIntegral<int32_t>();
- attributionSource.token = sp<BBinder>::make();
- sp<MediaRecorder> mr = new MediaRecorder(attributionSource);
- writer->setListener(mr);
-
- uint8_t baseOpLen = operations.size();
- uint8_t totalLen = baseOpLen;
- uint8_t maxSources;
- // Different writers support different amounts of sources.
- switch (writerType) {
- case StandardWriters::AAC:
- case StandardWriters::AAC_ADTS:
- case StandardWriters::AMR_NB:
- case StandardWriters::AMR_WB:
- case StandardWriters::OGG:
- maxSources = 1;
- break;
- case StandardWriters::WEBM:
- maxSources = 2;
- break;
- default:
- maxSources = UINT8_MAX;
- break;
- }
- // Initialize some number of sources and add them to our writer.
- uint8_t sourceCount = dataProvider.ConsumeIntegralInRange<uint8_t>(0, maxSources);
- for (uint8_t i = 0; i < sourceCount; i++) {
- addSource(&dataProvider, writer);
+ sp<MediaWriter> writer = createWriter(fd, writerType, writerMeta, &fdp);
+ if (writer == nullptr) {
+ close(fd);
+ return 0;
}
- // Increase our range if additional operations are implemented.
- // Currently only MPEG4 has additiona public operations on their writer.
- if (writerType == StandardWriters::MPEG4) {
- totalLen += mpeg4Operations.size();
+ if (writerType == StandardWriters::WEBM) {
+ // This range is set to avoid CHECK failure in WEBMWriter::reset() -> EbmlVoid::EBmlVoid().
+ writer->setMaxFileSize(fdp.ConsumeIntegralInRange<int64_t>(5 * 1024 * 1024, INT64_MAX));
+ } else {
+ writer->setMaxFileSize(fdp.ConsumeIntegral<int64_t>());
}
+ writer->setMaxFileDuration(fdp.ConsumeIntegral<int64_t>());
+ writer->setCaptureRate(fdp.ConsumeFloatingPoint<float>());
- // Many operations require the writer to be started.
- writer->start(fileMeta.get());
- for (size_t ops_run = 0; dataProvider.remaining_bytes() > 0 && ops_run < kMaxOperations - 1;
- ops_run++) {
- uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, totalLen - 1);
- if (op < baseOpLen) {
- operations[op](&dataProvider, writer, fileMeta, tf.fd);
- } else if (writerType == StandardWriters::MPEG4) {
- mpeg4Operations[op - baseOpLen](&dataProvider, (MPEG4Writer*)writer.get());
- } else {
- // Here just in case, will error out.
- operations[op](&dataProvider, writer, fileMeta, tf.fd);
- }
- }
+ sp<MediaSource> source = createSource(writerType, &fdp);
+ writer->addSource(source);
+ writer->start(writerMeta.get());
+ writer->pause();
writer->stop();
- writer.clear();
- writer = nullptr;
+ close(fd);
+
return 0;
}
} // namespace android