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

Commit 5e561af6 authored by Steven Moreland's avatar Steven Moreland
Browse files

binder_parcel_fuzzer: construct parcels w/ objects

Better coverage, since before we didn't test read methods that might get
ahold of valid objects. This is in preparation of exporting and using
these randomly generated parcel objects elsewhere.

Bug: N/A
Test: binder_parcel_fuzzer
Change-Id: Iac53cbe0437cea39a0d94177abe4e33d50eb189e
parent 842b593c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ cc_fuzz {
        "binder_ndk.cpp",
        "hwbinder.cpp",
        "main.cpp",
        "random_fd.cpp",
        "random_parcel.cpp",
        "util.cpp",
    ],
    static_libs: [
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <binder/Parcel.h>
#include <vector>
+4 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <android/binder_auto_utils.h>
#include <vector>
@@ -31,6 +32,9 @@ public:
    const AParcel* aParcel() const { return mParcel.get(); }
    AParcel* aParcel() { return mParcel.get(); }

    android::Parcel* parcel() { return aParcel()->get(); }

    const uint8_t* data() const { return aParcel()->get()->data(); }
    size_t dataSize() const { return aParcel()->get()->dataSize(); }
    size_t dataAvail() const { return aParcel()->get()->dataAvail(); }
    size_t dataPosition() const { return aParcel()->get()->dataPosition(); }
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <hwbinder/Parcel.h>
#include <vector>
+24 −17
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "binder.h"
#include "binder_ndk.h"
#include "hwbinder.h"
#include "random_parcel.h"
#include "util.h"

#include <android-base/logging.h>
@@ -26,29 +27,33 @@
#include <cstdlib>
#include <ctime>

using android::fillRandomParcel;

void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
    std::vector<uint8_t> input = provider.ConsumeRemainingBytes<uint8_t>();
    p->setData(input.data(), input.size());
}

template <typename P>
void doFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads,
            FuzzedDataProvider* provider) {
            FuzzedDataProvider&& provider) {
    // Allow some majority of the bytes to be dedicated to telling us what to
    // do. The fixed value added here represents that we want to test doing a
    // lot of 'instructions' even on really short parcels.
    size_t maxInstructions = 20 + (provider->remaining_bytes() * 2 / 3);
    size_t maxInstructions = 20 + (provider.remaining_bytes() * 2 / 3);
    // but don't always use that many instructions. We want to allow the fuzzer
    // to explore large parcels with few instructions if it wants to.
    std::vector<uint8_t> instructions = provider->ConsumeBytes<uint8_t>(
            provider->ConsumeIntegralInRange<size_t>(0, maxInstructions));

    // TODO: generate 'objects' data
    std::vector<uint8_t> input = provider->ConsumeRemainingBytes<uint8_t>();
    std::vector<uint8_t> instructions = provider.ConsumeBytes<uint8_t>(
            provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));

    P p;
    p.setData(input.data(), input.size());
    fillRandomParcel(&p, std::move(provider));

    // since we are only using a byte to index
    CHECK(reads.size() <= 255) << reads.size();

    FUZZ_LOG() << "backend: " << backend;
    FUZZ_LOG() << "input: " << hexString(input);
    FUZZ_LOG() << "input: " << hexString(p.data(), p.dataSize());
    FUZZ_LOG() << "instructions: " << hexString(instructions);

    for (size_t i = 0; i + 1 < instructions.size(); i += 2) {
@@ -75,20 +80,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {

    FuzzedDataProvider provider = FuzzedDataProvider(data, size);

    const std::function<void(FuzzedDataProvider*)> fuzzBackend[3] = {
            [](FuzzedDataProvider* provider) {
    const std::function<void(FuzzedDataProvider &&)> fuzzBackend[3] = {
            [](FuzzedDataProvider&& provider) {
                doFuzz<::android::hardware::Parcel>("hwbinder", HWBINDER_PARCEL_READ_FUNCTIONS,
                                                    provider);
                                                    std::move(provider));
            },
            [](FuzzedDataProvider* provider) {
                doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS, provider);
            [](FuzzedDataProvider&& provider) {
                doFuzz<::android::Parcel>("binder", BINDER_PARCEL_READ_FUNCTIONS,
                                          std::move(provider));
            },
            [](FuzzedDataProvider* provider) {
                doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS, provider);
            [](FuzzedDataProvider&& provider) {
                doFuzz<NdkParcelAdapter>("binder_ndk", BINDER_NDK_PARCEL_READ_FUNCTIONS,
                                         std::move(provider));
            },
    };

    provider.PickValueInArray(fuzzBackend)(&provider);
    provider.PickValueInArray(fuzzBackend)(std::move(provider));

    return 0;
}
Loading