Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9114fc5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Refactored libstagefright_writer_fuzzer" into main

parents 0ab78043 7e9eeca4
Loading
Loading
Loading
Loading
+225 −74
Original line number Diff line number Diff line
@@ -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<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> writerMeta,
                             FuzzedDataProvider* fdp) {
    sp<MediaWriter> writer;

    if (fdp->ConsumeBool()) {
        writerMeta->setInt32(kKeyRealTimeRecording, fdp->ConsumeBool());
    }

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();
    switch (writerType) {
        case AAC:
            writer = sp<AACWriter>::make(fd);

    sp<DataSource> source =
        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri.c_str());
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
            }
            break;
        case AAC_ADTS:
            writer = sp<AACWriter>::make(fd);

    if (source == NULL) {
        return NULL;
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
            }
            break;
        case AMR_NB:
            writer = sp<AMRWriter>::make(fd);

    return MediaExtractorFactory::Create(source);
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
            }
            break;
        case AMR_WB:
            writer = sp<AMRWriter>::make(fd);

sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize) {
    std::string mime = genMimeType(dataProvider);
    sp<IMediaExtractor> extractor = genMediaExtractor(dataProvider, mime, maxMediaBlobSize);
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
            }
            break;
        case MPEG2TS:
            writer = sp<MPEG2TSWriter>::make(fd);

    if (extractor == NULL) {
        return NULL;
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
            }
            break;
        case MPEG4:
            writer = sp<MPEG4Writer>::make(fd);

    for (size_t i = 0; i < extractor->countTracks(); ++i) {
        sp<MetaData> meta = extractor->getTrackMetaData(i);
            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);
            }

        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;
            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKey2ByteNalLength, fdp->ConsumeBool());
            }
            return new CallbackMediaSource(track);

            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyTimeScale,
                                     fdp->ConsumeIntegralInRange<int32_t>(600, 96000));
            }

            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKey4BitTrackIds, fdp->ConsumeBool());
            }

    return NULL;
            if (fdp->ConsumeBool()) {
                writerMeta->setInt64(kKeyTrackTimeStatus, fdp->ConsumeIntegral<int64_t>());
            }

sp<MediaWriter> createWriter(int fd, StandardWriters writerType, sp<MetaData> fileMeta) {
    sp<MediaWriter> writer;
    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);
            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 AAC_ADTS:
            writer = new AACWriter(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
        case OGG:
            writer = sp<OggWriter>::make(fd);

            if (fdp->ConsumeBool()) {
                writerMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
            }
            break;
        case WEBM:
            writer = new WebmWriter(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_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;
        case MPEG4:
            writer = new MPEG4Writer(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
    }

    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:
            writer = new AMRWriter(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
            meta->setInt32(kKeyChannelCount, 1);
            meta->setInt32(kKeySampleRate, 8000);
            break;
        case AMR_WB:
            writer = new AMRWriter(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
            meta->setInt32(kKeyChannelCount, 1);
            meta->setInt32(kKeySampleRate, 16000);
            break;
        case MPEG2TS:
            writer = new MPEG2TSWriter(fd);
            fileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_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;
        default:
            return nullptr;
        case MPEG4: {
            auto mime = fdp->PickValueInArray<std::string>(kMpeg4MimeTypes);
            meta->setCString(kKeyMIMEType, mime.c_str());

            if (fdp->ConsumeBool()) {
                meta->setInt32(kKeyBackgroundMode, fdp->ConsumeBool());
            }
    if (writer != nullptr) {
        fileMeta->setInt32(kKeyRealTimeRecording, false);

            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>());
                }
    return writer;

                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
+59 −59
Original line number Diff line number Diff line
@@ -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 @@ enum StandardWriters {
    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"};

std::string genMimeType(FuzzedDataProvider *dataProvider);
sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);

sp<MediaWriter> createWriter(int32_t fd, StandardWriters writerType, sp<MetaData> fileMeta);
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,

        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,

        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
+28 −195

File changed.

Preview size limit exceeded, changes collapsed.