/*
 * Copyright (C) 2021 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 <stddef.h>
#include <stdint.h>
#include <iostream>
#include <limits>
#include <thread>

#include <android-base/logging.h>
#include <fmq/AidlMessageQueue.h>
#include <fmq/ConvertMQDescriptors.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>

#include "fuzzer/FuzzedDataProvider.h"

using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using aidl::android::hardware::common::fmq::UnsynchronizedWrite;
using android::hardware::kSynchronizedReadWrite;
using android::hardware::kUnsynchronizedWrite;

typedef int32_t payload_t;

// The reader will wait for 10 ms
static constexpr int kBlockingTimeoutNs = 10000000;

/*
 * MessageQueueBase.h contains asserts when memory allocation fails. So we need
 * to set a reasonable limit if we want to avoid those asserts.
 */
static constexpr size_t kAlignment = 8;
static constexpr size_t kMaxNumElements = PAGE_SIZE * 10 / sizeof(payload_t) - kAlignment + 1;

/*
 * The read counter can be found in the shared memory 16 bytes before the start
 * of the ring buffer.
 */
static constexpr int kReadCounterOffsetBytes = 16;
/*
 * The write counter can be found in the shared memory 8 bytes before the start
 * of the ring buffer.
 */
static constexpr int kWriteCounterOffsetBytes = 8;

static constexpr int kMaxNumSyncReaders = 1;
static constexpr int kMaxNumUnsyncReaders = 5;
static constexpr int kMaxDataPerReader = 5;

typedef android::AidlMessageQueue<payload_t, SynchronizedReadWrite> AidlMessageQueueSync;
typedef android::AidlMessageQueue<payload_t, UnsynchronizedWrite> AidlMessageQueueUnsync;
typedef android::hardware::MessageQueue<payload_t, kSynchronizedReadWrite> MessageQueueSync;
typedef android::hardware::MessageQueue<payload_t, kUnsynchronizedWrite> MessageQueueUnsync;
typedef aidl::android::hardware::common::fmq::MQDescriptor<payload_t, SynchronizedReadWrite>
        AidlMQDescSync;
typedef aidl::android::hardware::common::fmq::MQDescriptor<payload_t, UnsynchronizedWrite>
        AidlMQDescUnsync;
typedef android::hardware::MQDescriptorSync<payload_t> MQDescSync;
typedef android::hardware::MQDescriptorUnsync<payload_t> MQDescUnsync;

static inline uint64_t* getCounterPtr(payload_t* start, int byteOffset) {
    return reinterpret_cast<uint64_t*>(reinterpret_cast<uint8_t*>(start) - byteOffset);
}

template <typename Queue, typename Desc>
void reader(const Desc& desc, std::vector<uint8_t> readerData, bool userFd) {
    Queue readMq(desc);
    if (!readMq.isValid()) {
        LOG(ERROR) << "read mq invalid";
        return;
    }
    FuzzedDataProvider fdp(&readerData[0], readerData.size());
    payload_t* ring = nullptr;
    while (fdp.remaining_bytes()) {
        typename Queue::MemTransaction tx;
        size_t numElements = fdp.ConsumeIntegralInRange<size_t>(0, kMaxNumElements);
        if (!readMq.beginRead(numElements, &tx)) {
            continue;
        }
        const auto& region = tx.getFirstRegion();
        payload_t* firstStart = region.getAddress();

        // the ring buffer is only next to the read/write counters when there is
        // no user supplied fd
        if (!userFd) {
            if (ring == nullptr) {
                ring = firstStart;
            }
            if (fdp.ConsumeIntegral<uint8_t>() == 1) {
                uint64_t* writeCounter = getCounterPtr(ring, kWriteCounterOffsetBytes);
                *writeCounter = fdp.ConsumeIntegral<uint64_t>();
            }
        }
        (void)std::to_string(*firstStart);

        readMq.commitRead(numElements);
    }
}

template <typename Queue, typename Desc>
void readerBlocking(const Desc& desc, std::vector<uint8_t> readerData) {
    Queue readMq(desc);
    if (!readMq.isValid()) {
        LOG(ERROR) << "read mq invalid";
        return;
    }
    FuzzedDataProvider fdp(&readerData[0], readerData.size());
    bool success;
    do {
        size_t count = fdp.remaining_bytes()
                               ? fdp.ConsumeIntegralInRange<size_t>(1, readMq.getQuantumCount())
                               : 1;
        std::vector<payload_t> data;
        data.resize(count);
        success = readMq.readBlocking(data.data(), count, kBlockingTimeoutNs);
    } while (success == true || fdp.remaining_bytes() > sizeof(size_t));
}

// Can't use blocking calls with Unsync queues(there is a static_assert)
template <>
void readerBlocking<AidlMessageQueueUnsync, AidlMQDescUnsync>(const AidlMQDescUnsync&,
                                                              std::vector<uint8_t>) {}
template <>
void readerBlocking<MessageQueueUnsync, MQDescUnsync>(const MQDescUnsync&, std::vector<uint8_t>) {}

template <typename Queue>
void writer(Queue& writeMq, FuzzedDataProvider& fdp, bool userFd) {
    payload_t* ring = nullptr;
    while (fdp.remaining_bytes()) {
        typename Queue::MemTransaction tx;
        size_t numElements = 1;
        if (!writeMq.beginWrite(numElements, &tx)) {
            // need to consume something so we don't end up looping forever
            fdp.ConsumeIntegral<uint8_t>();
            continue;
        }

        const auto& region = tx.getFirstRegion();
        payload_t* firstStart = region.getAddress();
        // the ring buffer is only next to the read/write counters when there is
        // no user supplied fd
        if (!userFd) {
            if (ring == nullptr) {
                ring = firstStart;
            }
            if (fdp.ConsumeIntegral<uint8_t>() == 1) {
                uint64_t* readCounter = getCounterPtr(ring, kReadCounterOffsetBytes);
                *readCounter = fdp.ConsumeIntegral<uint64_t>();
            }
        }
        *firstStart = fdp.ConsumeIntegral<payload_t>();

        writeMq.commitWrite(numElements);
    }
}

template <typename Queue>
void writerBlocking(Queue& writeMq, FuzzedDataProvider& fdp) {
    while (fdp.remaining_bytes() > sizeof(size_t)) {
        size_t count = fdp.ConsumeIntegralInRange<size_t>(1, writeMq.getQuantumCount());
        std::vector<payload_t> data;
        for (int i = 0; i < count; i++) {
            data.push_back(fdp.ConsumeIntegral<payload_t>());
        }
        writeMq.writeBlocking(data.data(), count, kBlockingTimeoutNs);
    }
}

// Can't use blocking calls with Unsync queues(there is a static_assert)
template <>
void writerBlocking<AidlMessageQueueUnsync>(AidlMessageQueueUnsync&, FuzzedDataProvider&) {}
template <>
void writerBlocking<MessageQueueUnsync>(MessageQueueUnsync&, FuzzedDataProvider&) {}

template <typename Queue, typename Desc>
void fuzzAidlWithReaders(std::vector<uint8_t>& writerData,
                         std::vector<std::vector<uint8_t>>& readerData, bool blocking) {
    FuzzedDataProvider fdp(&writerData[0], writerData.size());
    bool evFlag = blocking || fdp.ConsumeBool();
    android::base::unique_fd dataFd;
    size_t bufferSize = 0;
    size_t numElements = fdp.ConsumeIntegralInRange<size_t>(1, kMaxNumElements);
    bool userFd = fdp.ConsumeBool();
    if (userFd) {
        // run test with our own data region
        bufferSize = numElements * sizeof(payload_t);
        dataFd.reset(::ashmem_create_region("SyncReadWrite", bufferSize));
    }
    Queue writeMq(numElements, evFlag, std::move(dataFd), bufferSize);
    if (!writeMq.isValid()) {
        LOG(ERROR) << "AIDL write mq invalid";
        return;
    }
    const auto desc = writeMq.dupeDesc();
    CHECK(desc.handle.fds[0].get() != -1);

    std::vector<std::thread> clients;
    for (int i = 0; i < readerData.size(); i++) {
        if (blocking) {
            clients.emplace_back(readerBlocking<Queue, Desc>, std::ref(desc),
                                 std::ref(readerData[i]));
        } else {
            clients.emplace_back(reader<Queue, Desc>, std::ref(desc), std::ref(readerData[i]),
                                 userFd);
        }
    }

    if (blocking) {
        writerBlocking<Queue>(writeMq, fdp);
    } else {
        writer<Queue>(writeMq, fdp, userFd);
    }

    for (auto& client : clients) {
        client.join();
    }
}

template <typename Queue, typename Desc>
void fuzzHidlWithReaders(std::vector<uint8_t>& writerData,
                         std::vector<std::vector<uint8_t>>& readerData, bool blocking) {
    FuzzedDataProvider fdp(&writerData[0], writerData.size());
    bool evFlag = blocking || fdp.ConsumeBool();
    android::base::unique_fd dataFd;
    size_t bufferSize = 0;
    size_t numElements = fdp.ConsumeIntegralInRange<size_t>(1, kMaxNumElements);
    bool userFd = fdp.ConsumeBool();
    if (userFd) {
        // run test with our own data region
        bufferSize = numElements * sizeof(payload_t);
        dataFd.reset(::ashmem_create_region("SyncReadWrite", bufferSize));
    }
    Queue writeMq(numElements, evFlag, std::move(dataFd), bufferSize);
    if (!writeMq.isValid()) {
        LOG(ERROR) << "HIDL write mq invalid";
        return;
    }
    const auto desc = writeMq.getDesc();
    CHECK(desc->isHandleValid());

    std::vector<std::thread> clients;
    for (int i = 0; i < readerData.size(); i++) {
        if (blocking) {
            clients.emplace_back(readerBlocking<Queue, Desc>, std::ref(*desc),
                                 std::ref(readerData[i]));
        } else {
            clients.emplace_back(reader<Queue, Desc>, std::ref(*desc), std::ref(readerData[i]),
                                 userFd);
        }
    }

    if (blocking) {
        writerBlocking<Queue>(writeMq, fdp);
    } else {
        writer<Queue>(writeMq, fdp, userFd);
    }

    for (auto& client : clients) {
        client.join();
    }
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    if (size < 1 || size > 50000) {
        return 0;
    }
    FuzzedDataProvider fdp(data, size);

    bool fuzzSync = fdp.ConsumeBool();
    std::vector<std::vector<uint8_t>> readerData;
    uint8_t numReaders = fuzzSync ? fdp.ConsumeIntegralInRange<uint8_t>(0, kMaxNumSyncReaders)
                                  : fdp.ConsumeIntegralInRange<uint8_t>(0, kMaxNumUnsyncReaders);
    for (int i = 0; i < numReaders; i++) {
        readerData.emplace_back(fdp.ConsumeBytes<uint8_t>(kMaxDataPerReader));
    }
    bool fuzzBlocking = fdp.ConsumeBool();
    std::vector<uint8_t> writerData = fdp.ConsumeRemainingBytes<uint8_t>();
    if (fuzzSync) {
        fuzzHidlWithReaders<MessageQueueSync, MQDescSync>(writerData, readerData, fuzzBlocking);
        fuzzAidlWithReaders<AidlMessageQueueSync, AidlMQDescSync>(writerData, readerData,
                                                                  fuzzBlocking);
    } else {
        fuzzHidlWithReaders<MessageQueueUnsync, MQDescUnsync>(writerData, readerData, false);
        fuzzAidlWithReaders<AidlMessageQueueUnsync, AidlMQDescUnsync>(writerData, readerData,
                                                                      false);
    }

    return 0;
}
