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

Commit b2a7ea7d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add fuzzers for libutils classes" am: f3a570b8

Change-Id: Id8078b3b9356b8d64f1596102b1be598171ad4b2
parents 873a84ca f3a570b8
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -194,6 +194,45 @@ cc_library {
    },
}

cc_defaults {
    name: "libutils_fuzz_defaults",
    host_supported: true,
    shared_libs: [
        "libutils",
        "libbase",
    ],
}

cc_fuzz {
    name: "libutils_fuzz_bitset",
    defaults: ["libutils_fuzz_defaults"],
    srcs: ["BitSet_fuzz.cpp"],
}

cc_fuzz {
    name: "libutils_fuzz_filemap",
    defaults: ["libutils_fuzz_defaults"],
    srcs: ["FileMap_fuzz.cpp"],
}

cc_fuzz {
    name: "libutils_fuzz_string8",
    defaults: ["libutils_fuzz_defaults"],
    srcs: ["String8_fuzz.cpp"],
}

cc_fuzz {
    name: "libutils_fuzz_string16",
    defaults: ["libutils_fuzz_defaults"],
    srcs: ["String16_fuzz.cpp"],
}

cc_fuzz {
    name: "libutils_fuzz_vector",
    defaults: ["libutils_fuzz_defaults"],
    srcs: ["Vector_fuzz.cpp"],
}

cc_test {
    name: "libutils_test",
    host_supported: true,
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 <functional>

#include "fuzzer/FuzzedDataProvider.h"
#include "utils/BitSet.h"
static constexpr uint8_t MAX_OPERATIONS = 50;

// We need to handle both 32 and 64 bit bitsets, so we use a function template
// here. Sadly, std::function can't be generic, so we generate a vector of
// std::functions using this function.
template <typename T>
std::vector<std::function<void(T, uint32_t)>> getOperationsForType() {
    return {
            [](T bs, uint32_t val) -> void { bs.markBit(val); },
            [](T bs, uint32_t val) -> void { bs.valueForBit(val); },
            [](T bs, uint32_t val) -> void { bs.hasBit(val); },
            [](T bs, uint32_t val) -> void { bs.clearBit(val); },
            [](T bs, uint32_t val) -> void { bs.getIndexOfBit(val); },
            [](T bs, uint32_t) -> void { bs.clearFirstMarkedBit(); },
            [](T bs, uint32_t) -> void { bs.markFirstUnmarkedBit(); },
            [](T bs, uint32_t) -> void { bs.clearLastMarkedBit(); },
            [](T bs, uint32_t) -> void { bs.clear(); },
            [](T bs, uint32_t) -> void { bs.count(); },
            [](T bs, uint32_t) -> void { bs.isEmpty(); },
            [](T bs, uint32_t) -> void { bs.isFull(); },
            [](T bs, uint32_t) -> void { bs.firstMarkedBit(); },
            [](T bs, uint32_t) -> void { bs.lastMarkedBit(); },
    };
}

// Our operations for 32 and 64 bit bitsets
static const std::vector<std::function<void(android::BitSet32, uint32_t)>> thirtyTwoBitOps =
        getOperationsForType<android::BitSet32>();
static const std::vector<std::function<void(android::BitSet64, uint32_t)>> sixtyFourBitOps =
        getOperationsForType<android::BitSet64>();

void runOperationFor32Bit(android::BitSet32 bs, uint32_t bit, uint8_t operation) {
    thirtyTwoBitOps[operation](bs, bit);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider dataProvider(data, size);
    uint32_t thirty_two_base = dataProvider.ConsumeIntegral<uint32_t>();
    uint64_t sixty_four_base = dataProvider.ConsumeIntegral<uint64_t>();
    android::BitSet32 b1 = android::BitSet32(thirty_two_base);
    android::BitSet64 b2 = android::BitSet64(sixty_four_base);

    size_t opsRun = 0;
    while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
        uint32_t bit = dataProvider.ConsumeIntegral<uint32_t>();
        uint8_t op = dataProvider.ConsumeIntegral<uint8_t>();
        thirtyTwoBitOps[op % thirtyTwoBitOps.size()](b1, bit);
        sixtyFourBitOps[op % sixtyFourBitOps.size()](b2, bit);
    }
    return 0;
}
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 <iostream>

#include "android-base/file.h"
#include "fuzzer/FuzzedDataProvider.h"
#include "utils/FileMap.h"

static constexpr uint16_t MAX_STR_SIZE = 256;
static constexpr uint8_t MAX_FILENAME_SIZE = 32;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider dataProvider(data, size);
    TemporaryFile tf;
    // Generate file contents
    std::string contents = dataProvider.ConsumeRandomLengthString(MAX_STR_SIZE);
    // If we have string contents, dump them into the file.
    // Otherwise, just leave it as an empty file.
    if (contents.length() > 0) {
        const char* bytes = contents.c_str();
        android::base::WriteStringToFd(bytes, tf.fd);
    }
    android::FileMap m;
    // Generate create() params
    std::string orig_name = dataProvider.ConsumeRandomLengthString(MAX_FILENAME_SIZE);
    size_t length = dataProvider.ConsumeIntegralInRange<size_t>(1, SIZE_MAX);
    off64_t offset = dataProvider.ConsumeIntegralInRange<off64_t>(1, INT64_MAX);
    bool read_only = dataProvider.ConsumeBool();
    m.create(orig_name.c_str(), tf.fd, offset, length, read_only);
    m.getDataOffset();
    m.getFileName();
    m.getDataLength();
    m.getDataPtr();
    int enum_index = dataProvider.ConsumeIntegral<int>();
    m.advise(static_cast<android::FileMap::MapAdvice>(enum_index));
    return 0;
}
+122 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 <iostream>

#include "fuzzer/FuzzedDataProvider.h"
#include "utils/String16.h"
static constexpr int MAX_STRING_BYTES = 256;
static constexpr uint8_t MAX_OPERATIONS = 50;

std::vector<std::function<void(FuzzedDataProvider&, android::String16, android::String16)>>
        operations = {

                // Bytes and size
                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
                    str1.string();
                }),
                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
                    str1.isStaticString();
                }),
                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
                    str1.size();
                }),

                // Casing
                ([](FuzzedDataProvider&, android::String16 str1, android::String16) -> void {
                    str1.makeLower();
                }),

                // Comparison
                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                    str1.startsWith(str2);
                }),
                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                    str1.contains(str2.string());
                }),
                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                    str1.compare(str2);
                }),

                // Append and format
                ([](FuzzedDataProvider&, android::String16 str1, android::String16 str2) -> void {
                    str1.append(str2);
                }),
                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                    android::String16 str2) -> void {
                    int pos = dataProvider.ConsumeIntegralInRange<int>(0, str1.size());
                    str1.insert(pos, str2.string());
                }),

                // Find and replace operations
                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                    android::String16) -> void {
                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
                    str1.findFirst(findChar);
                }),
                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                    android::String16) -> void {
                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
                    str1.findLast(findChar);
                }),
                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                    android::String16) -> void {
                    char16_t findChar = dataProvider.ConsumeIntegral<char16_t>();
                    char16_t replaceChar = dataProvider.ConsumeIntegral<char16_t>();
                    str1.replaceAll(findChar, replaceChar);
                }),
                ([](FuzzedDataProvider& dataProvider, android::String16 str1,
                    android::String16) -> void {
                    size_t len = dataProvider.ConsumeIntegral<size_t>();
                    size_t begin = dataProvider.ConsumeIntegral<size_t>();
                    str1.remove(len, begin);
                }),
};

void callFunc(uint8_t index, FuzzedDataProvider& dataProvider, android::String16 str1,
              android::String16 str2) {
    operations[index](dataProvider, str1, str2);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider dataProvider(data, size);
    // We're generating two char vectors.
    // First, generate lengths.
    const size_t kVecOneLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
    const size_t kVecTwoLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);

    // Next, populate the vectors
    std::vector<char> vec = dataProvider.ConsumeBytesWithTerminator<char>(kVecOneLen);
    std::vector<char> vec_two = dataProvider.ConsumeBytesWithTerminator<char>(kVecTwoLen);

    // Get pointers to their data
    char* char_one = vec.data();
    char* char_two = vec_two.data();

    // Create UTF16 representations
    android::String16 str_one_utf16 = android::String16(char_one);
    android::String16 str_two_utf16 = android::String16(char_two);

    // Run operations against strings
    int opsRun = 0;
    while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
        uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
        callFunc(op, dataProvider, str_one_utf16, str_two_utf16);
    }

    str_one_utf16.remove(0, str_one_utf16.size());
    str_two_utf16.remove(0, str_two_utf16.size());
    return 0;
}
+136 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 <functional>
#include <iostream>

#include "fuzzer/FuzzedDataProvider.h"
#include "utils/String8.h"

static constexpr int MAX_STRING_BYTES = 256;
static constexpr uint8_t MAX_OPERATIONS = 50;

std::vector<std::function<void(FuzzedDataProvider&, android::String8, android::String8)>>
        operations = {

                // Bytes and size
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.bytes();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.isEmpty();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.length();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.size();
                },

                // Casing
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.toUpper();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.toLower();
                },

                [](FuzzedDataProvider&, android::String8 str1, android::String8 str2) -> void {
                    str1.removeAll(str2.c_str());
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8 str2) -> void {
                    str1.compare(str2);
                },

                // Append and format
                [](FuzzedDataProvider&, android::String8 str1, android::String8 str2) -> void {
                    str1.append(str2);
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8 str2) -> void {
                    str1.appendFormat(str1.c_str(), str2.c_str());
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8 str2) -> void {
                    str1.format(str1.c_str(), str2.c_str());
                },

                // Find operation
                [](FuzzedDataProvider& dataProvider, android::String8 str1,
                   android::String8) -> void {
                    // We need to get a value from our fuzzer here.
                    int start_index = dataProvider.ConsumeIntegralInRange<int>(0, str1.size());
                    str1.find(str1.c_str(), start_index);
                },

                // Path handling
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.getBasePath();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.getPathExtension();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.getPathLeaf();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.getPathDir();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    str1.convertToResPath();
                },
                [](FuzzedDataProvider&, android::String8 str1, android::String8) -> void {
                    android::String8 path_out_str = android::String8();
                    str1.walkPath(&path_out_str);
                    path_out_str.clear();
                },
                [](FuzzedDataProvider& dataProvider, android::String8 str1,
                   android::String8) -> void {
                    str1.setPathName(dataProvider.ConsumeBytesWithTerminator<char>(5).data());
                },
                [](FuzzedDataProvider& dataProvider, android::String8 str1,
                   android::String8) -> void {
                    str1.appendPath(dataProvider.ConsumeBytesWithTerminator<char>(5).data());
                },
};

void callFunc(uint8_t index, FuzzedDataProvider& dataProvider, android::String8 str1,
              android::String8 str2) {
    operations[index](dataProvider, str1, str2);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider dataProvider(data, size);
    // Generate vector lengths
    const size_t kVecOneLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
    const size_t kVecTwoLen = dataProvider.ConsumeIntegralInRange<size_t>(1, MAX_STRING_BYTES);
    // Populate vectors
    std::vector<char> vec = dataProvider.ConsumeBytesWithTerminator<char>(kVecOneLen);
    std::vector<char> vec_two = dataProvider.ConsumeBytesWithTerminator<char>(kVecTwoLen);
    // Create UTF-8 pointers
    android::String8 str_one_utf8 = android::String8(vec.data());
    android::String8 str_two_utf8 = android::String8(vec_two.data());

    // Run operations against strings
    int opsRun = 0;
    while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
        uint8_t op = dataProvider.ConsumeIntegralInRange<uint8_t>(0, operations.size() - 1);
        callFunc(op, dataProvider, str_one_utf8, str_two_utf8);
    }

    // Just to be extra sure these can be freed, we're going to explicitly clear
    // them
    str_one_utf8.clear();
    str_two_utf8.clear();
    return 0;
}
Loading