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

Commit 9c4b2297 authored by Devendra Singhi's avatar Devendra Singhi Committed by Ayushi Khopkar
Browse files

Add rtp_writer_fuzzer

exec/sec : 1000
Test: ./rtp_writer_fuzzer
Bug: 240525358

Change-Id: I7027289106e07282a5199f78f7a786577eb5d3a2
(cherry picked from commit a374ca38543e03cf206e7eb40b6483971991cdd2)
parent e9410b6e
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -46,3 +46,19 @@ cc_fuzz {
        "libstagefright_rtsp_fuzzer_defaults",
    ]
}

cc_fuzz {
    name: "rtp_writer_fuzzer",
    srcs: [
        "rtp_writer_fuzzer.cpp",
    ],
    defaults: [
        "libstagefright_rtsp_fuzzer_defaults",
    ],
    shared_libs:[
        "libandroid_net",
        "libbase",
        "libstagefright",
        "libcutils",
    ],
}
+36 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

## Table of contents
+ [sdploader_fuzzer](#SDPLoader)
+ [rtp_writer_fuzzer](#ARTPWriter)

# <a name="SDPLoader"></a> Fuzzer for SDPLoader

@@ -26,3 +27,38 @@ SDPLoader supports the following parameters:
  $ adb sync data
  $ adb shell /data/fuzz/arm64/sdploader_fuzzer/sdploader_fuzzer
```

# <a name="ARTPWriter"></a> Fuzzer for ARTPWriter

ARTPWriter supports the following parameters:
1. File descriptor (parameter name: "fd")
2. Local Ip (parameter name: "localIp")
3. Local Port (parameter name: "localPort")
4. Remote Ip (parameter name: "remoteIp")
5. Remote Port (parameter name: "remotePort")
6. Sequence No (parameter name: "seqNo")
7. OpponentID (parameter name: "opponentID")
8. Bit Rate (parameter name: "bitrate")
9. kKeyMIMETypeArray (parameter name: "mimeType")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`localIp`| `String` |Value obtained from FuzzedDataProvider|
|`localPort`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
|`remoteIp`| `String` |Value obtained from FuzzedDataProvider|
|`remotePort`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
|`seqNo`| `0`  to  `10000000` |Value obtained from FuzzedDataProvider|
|`opponentID`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
|`bitrate`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
|`mimeType`| 0. `MEDIA_MIMETYPE_VIDEO_AVC`<br> 1. `MEDIA_MIMETYPE_VIDEO_HEVC`<br> 2. `MEDIA_MIMETYPE_VIDEO_H263`<br> 3. `MEDIA_MIMETYPE_AUDIO_AMR_NB`<br> 4. `MEDIA_MIMETYPE_AUDIO_AMR_WB`|Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) rtp_writer_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/rtp_writer_fuzzer/rtp_writer_fuzzer
```
+184 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <fuzzer/FuzzedDataProvider.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/rtsp/ARTPWriter.h>

constexpr int32_t kMinSize = 0;
constexpr int32_t kMaxSize = 65536;
constexpr int32_t kMaxTime = 1000;
constexpr int32_t kMaxBytes = 128;
constexpr int32_t kAMRNBFrameSizes[] = {13, 14, 16, 18, 20, 21, 27, 32};
constexpr int32_t kAMRWBFrameSizes[] = {18, 24, 33, 37, 41, 47, 51, 59, 61};
constexpr int32_t kAMRIndexOffset = 8;

using namespace android;

const char* kKeyMimeTypeArray[] = {MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_HEVC,
                                   MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AMR_NB,
                                   MEDIA_MIMETYPE_AUDIO_AMR_WB};

struct TestMediaSource : public MediaSource {
  public:
    TestMediaSource(FuzzedDataProvider& mFdp) : mTestMetaData(new MetaData) {
        int32_t vectorSize = 0;
        mAllowRead = mFdp.ConsumeBool();
        mKeySps = mFdp.ConsumeIntegral<int32_t>();
        mKeyVps = mFdp.ConsumeIntegral<int32_t>();
        mKeyPps = mFdp.ConsumeIntegral<int32_t>();
        mKeyTime = mFdp.ConsumeIntegralInRange<int64_t>(kMinSize, kMaxTime);

        mMimeType = mFdp.PickValueInArray(kKeyMimeTypeArray);
        mTestMetaData->setCString(kKeyMIMEType, mMimeType);
        if (mMimeType == MEDIA_MIMETYPE_AUDIO_AMR_NB) {
            int32_t index =
                    mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, std::size(kAMRNBFrameSizes) - 1);
            vectorSize = kAMRNBFrameSizes[index];
            mData.push_back(kAMRIndexOffset * index);
        } else if (mMimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB) {
            int32_t index =
                    mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, std::size(kAMRWBFrameSizes) - 1);
            vectorSize = kAMRWBFrameSizes[index];
            mData.push_back(kAMRIndexOffset * index);
        } else if (mMimeType == MEDIA_MIMETYPE_VIDEO_H263) {
            // Required format for H263 media data
            mData.push_back(0);
            mData.push_back(0);
            vectorSize = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
        } else {
            vectorSize = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
        }
        for (size_t idx = mData.size(); idx < vectorSize; ++idx) {
            mData.push_back(mFdp.ConsumeIntegral<uint8_t>());
        }
    }
    virtual status_t start(MetaData* /*params*/) { return OK; }
    virtual status_t stop() { return OK; }
    virtual sp<MetaData> getFormat() { return mTestMetaData; }
    virtual status_t read(MediaBufferBase** buffer, const ReadOptions* /*options*/) {
        if (!mAllowRead) {
            return -1;
        }
        *buffer = new MediaBuffer(mData.data() /*data*/, mData.size() /*size*/);
        if (mKeySps) {
            (*buffer)->meta_data().setInt32(kKeySps, mKeySps);
        }
        if (mKeyVps) {
            (*buffer)->meta_data().setInt32(kKeyVps, mKeyVps);
        }
        if (mKeyPps) {
            (*buffer)->meta_data().setInt32(kKeyPps, mKeyPps);
        }
        (*buffer)->meta_data().setInt64(kKeyTime, mKeyTime);
        return OK;
    }

  private:
    int32_t mKeySps;
    int32_t mKeyVps;
    int32_t mKeyPps;
    int64_t mKeyTime;
    bool mAllowRead;
    const char* mMimeType;
    sp<MetaData> mTestMetaData;
    std::vector<uint8_t> mData;
};

class ARTPWriterFuzzer {
  public:
    ARTPWriterFuzzer(const uint8_t* data, size_t size)
        : mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)), mFdp(data, size) {}
    ~ARTPWriterFuzzer() { close(mDataSourceFd); }
    void process();

  private:
    void createARTPWriter();
    const int32_t mDataSourceFd;
    FuzzedDataProvider mFdp;
    sp<ARTPWriter> mArtpWriter;
};

void ARTPWriterFuzzer::createARTPWriter() {
    String8 localIp = String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
    String8 remoteIp = String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
    mArtpWriter = sp<ARTPWriter>::make(
            mDataSourceFd, localIp, mFdp.ConsumeIntegral<uint16_t>() /* localPort */, remoteIp,
            mFdp.ConsumeIntegral<uint16_t>() /* remotePort */,
            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize) /* seqNo */);
}

void ARTPWriterFuzzer::process() {
    if (mFdp.ConsumeBool()) {
        mArtpWriter = sp<ARTPWriter>::make(mDataSourceFd);
        if (mArtpWriter->getSequenceNum() > kMaxSize) {
            createARTPWriter();
        }
    } else {
        createARTPWriter();
    }

    mArtpWriter->addSource(sp<TestMediaSource>::make(mFdp) /* source */);

    while (mFdp.remaining_bytes()) {
        auto invokeRTPWriterFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
                [&]() {
                    sp<MetaData> metaData = sp<MetaData>::make();
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt32(kKeySelfID, mFdp.ConsumeIntegral<int32_t>());
                    }
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt32(kKeyPayloadType, mFdp.ConsumeIntegral<int32_t>());
                    }
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt32(kKeyRtpExtMap, mFdp.ConsumeIntegral<int32_t>());
                    }
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt32(kKeyRtpCvoDegrees, mFdp.ConsumeIntegral<int32_t>());
                    }
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt32(kKeyRtpDscp, mFdp.ConsumeIntegral<int32_t>());
                    }
                    if (mFdp.ConsumeBool()) {
                        metaData->setInt64(kKeySocketNetwork, mFdp.ConsumeIntegral<int64_t>());
                    }
                    mArtpWriter->start(metaData.get() /*param*/);
                },
                [&]() {
                    mArtpWriter->setTMMBNInfo(mFdp.ConsumeIntegral<uint32_t>() /* opponentID */,
                                              mFdp.ConsumeIntegral<uint32_t>() /* bitrate */);
                },
                [&]() { mArtpWriter->stop(); },
                [&]() {
                    mArtpWriter->updateCVODegrees(mFdp.ConsumeIntegral<int32_t>() /* cvoDegrees */);
                },
                [&]() {
                    mArtpWriter->updatePayloadType(
                            mFdp.ConsumeIntegral<int32_t>() /* payloadType */);
                },

        });
        invokeRTPWriterFuzzer();
    }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    ARTPWriterFuzzer artpWriterFuzzer(data, size);
    artpWriterFuzzer.process();
    return 0;
}