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

Commit e9410b6e authored by Aditya Vasu Wazir's avatar Aditya Vasu Wazir Committed by Ayushi Khopkar
Browse files

Add sdploader_fuzzer

exec/s : 1500
Test: ./sdploader_fuzzer
Bug: 240525358

Change-Id: I1f2dc971f86b7e5353478ef6708c36e0d9fb41ed
(cherry picked from commit dbef9bc45f9f1c47e17569d34a2de5fb0815d1e7)
parent 0990169b
Loading
Loading
Loading
Loading
+48 −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.
*/

cc_defaults {
    name: "libstagefright_rtsp_fuzzer_defaults",
    shared_libs: [
        "liblog",
        "libmedia",
        "libutils",
        "libstagefright_foundation",
    ],
    static_libs: [
        "libdatasource",
        "libstagefright_rtsp",
    ],
    header_libs: [
        "libstagefright_rtsp_headers",
    ],
    fuzz_config:{
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 155276,
    },
}

cc_fuzz {
    name: "sdploader_fuzzer",
    srcs: [
        "sdploader_fuzzer.cpp",
    ],
    defaults: [
        "libstagefright_rtsp_fuzzer_defaults",
    ]
}
+28 −0
Original line number Diff line number Diff line
# Fuzzers for libstagefright_rtsp

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

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

SDPLoader supports the following parameters:
1. Flag (parameter name: "flags")
2. URL (parameter name: "url")
3. Header (parameter name: "headers")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`flags`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
|`url`| `String` |Value obtained from FuzzedDataProvider|
|`headers`| `String` |Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) sdploader_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/sdploader_fuzzer/sdploader_fuzzer
```
+143 −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 <datasource/HTTPBase.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/MediaHTTPConnection.h>
#include <media/MediaHTTPService.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/rtsp/SDPLoader.h>

using namespace android;

constexpr int32_t kMinCapacity = 0;
constexpr int32_t kMaxCapacity = 1000;
constexpr int32_t kMaxStringLength = 20;
constexpr int32_t kMaxBytes = 128;
enum { kWhatLoad = 'load' };

struct FuzzAHandler : public AHandler {
  public:
    FuzzAHandler(std::function<void()> signalEosFunction) : mSignalEosFunction(signalEosFunction) {}

  protected:
    void onMessageReceived(const sp<AMessage>& msg) override {
        switch (msg->what()) {
            case kWhatLoad: {
                mSignalEosFunction();
                break;
            }
        }
        return;
    }

  private:
    std::function<void()> mSignalEosFunction;
};

struct FuzzMediaHTTPConnection : public MediaHTTPConnection {
  public:
    FuzzMediaHTTPConnection(FuzzedDataProvider* fdp) : mFdp(fdp) {
        mSize = mFdp->ConsumeIntegralInRange(kMinCapacity, kMaxCapacity);
        mData = mFdp->ConsumeBytes<uint8_t>(mSize);
        mSize = mData.size();
    }
    virtual bool connect(const char* /* uri */,
                         const KeyedVector<String8, String8>* /* headers */) {
        return mFdp->ConsumeBool();
    }
    virtual void disconnect() { return; }
    virtual ssize_t readAt(off64_t offset, void* data, size_t size) {
        if (size <= mSize - offset) {
            data = mData.data() + offset;
            return size;
        } else {
            data = nullptr;
            return 0;
        }
    }
    virtual off64_t getSize() { return mSize; }
    virtual status_t getMIMEType(String8* /*mimeType*/) {return mFdp->ConsumeIntegral<status_t>();}
    virtual status_t getUri(String8* /*uri*/) {return mFdp->ConsumeIntegral<status_t>();}

  private:
    FuzzedDataProvider* mFdp = nullptr;
    std::vector<uint8_t> mData;
    size_t mSize = 0;
};

struct FuzzMediaHTTPService : public MediaHTTPService {
  public:
    FuzzMediaHTTPService(FuzzedDataProvider* fdp) : mFdp(fdp) {}
    virtual sp<MediaHTTPConnection> makeHTTPConnection() {
        mediaHTTPConnection = sp<FuzzMediaHTTPConnection>::make(mFdp);
        return mediaHTTPConnection;
    }

  private:
    sp<FuzzMediaHTTPConnection> mediaHTTPConnection = nullptr;
    FuzzedDataProvider* mFdp = nullptr;
};

class SDPLoaderFuzzer {
  public:
    SDPLoaderFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {}
    void process();

  private:
    void signalEos();

    bool mEosReached = false;
    std::mutex mMsgPostCompleteMutex;
    std::condition_variable mConditionalVariable;
    FuzzedDataProvider mFdp;
};

void SDPLoaderFuzzer::signalEos() {
    mEosReached = true;
    mConditionalVariable.notify_one();
    return;
}

void SDPLoaderFuzzer::process() {
    sp<FuzzAHandler> handler = sp<FuzzAHandler>::make(std::bind(&SDPLoaderFuzzer::signalEos, this));
    sp<ALooper> looper = sp<ALooper>::make();
    looper->start();
    looper->registerHandler(handler);
    const sp<AMessage> notify = sp<AMessage>::make(kWhatLoad, handler);
    sp<SDPLoader> sdpLoader =
            sp<SDPLoader>::make(notify, mFdp.ConsumeIntegral<uint32_t>() /* flags */,
                                sp<FuzzMediaHTTPService>::make(&mFdp) /* httpService */);

    KeyedVector<String8, String8> headers;
    for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange<size_t>(kMinCapacity, kMaxCapacity);
         ++idx) {
        headers.add(String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()) /* key */,
                    String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()) /* value */);
    }

    sdpLoader->load(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* url */, &headers);

    std::unique_lock waitForMsgPostComplete(mMsgPostCompleteMutex);
    mConditionalVariable.wait(waitForMsgPostComplete, [this] { return mEosReached; });
}

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