Add PixelStreamMangerFuzzer with guided input
Bug: 160002800
Test: adb shell ./data/fuzz/arm64/computepipe_pixel_mem_handle_fuzzer/computepipe_pixel_mem_handle_fuzzer
Change-Id: I235e44e8ab26a2e431624a0b03a24022820e7f45
Merged-In: I235e44e8ab26a2e431624a0b03a24022820e7f45
(cherry picked from commit 801ab199f927c294ab49869302864a3474b48350)
diff --git a/computepipe/tests/fuzz/Android.bp b/computepipe/tests/fuzz/Android.bp
index dff74b8..97f3435 100644
--- a/computepipe/tests/fuzz/Android.bp
+++ b/computepipe/tests/fuzz/Android.bp
@@ -12,10 +12,28 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_fuzz {
- name: "computepipe_semantic_manager_fuzzer",
+cc_library_static {
+ name: "libcomputepipeprotosfuzz",
+ proto: {
+ export_proto_headers: true,
+ },
+ shared_libs: ["libprotobuf-cpp-full"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
srcs: [
- "SemanticManagerFuzzer.cpp",
+ "Fuzz.proto",
+ ],
+}
+
+cc_defaults {
+ name: "libcomputepipefuzz-defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
],
static_libs: [
"computepipe_runner_component",
@@ -39,3 +57,26 @@
"packages/services/Car/computepipe/runner/stream_manager",
],
}
+
+cc_fuzz {
+ name: "computepipe_semantic_manager_fuzzer",
+ defaults: ["libcomputepipefuzz-defaults"],
+ srcs: [
+ "SemanticManagerFuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "computepipe_pixel_mem_handle_fuzzer",
+ defaults: ["libcomputepipefuzz-defaults"],
+ srcs: [
+ "PixelMemHandleFuzzer.cpp",
+ ],
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ ],
+ static_libs: [
+ "libcomputepipeprotosfuzz",
+ "libprotobuf-mutator",
+ ],
+}
diff --git a/computepipe/tests/fuzz/Fuzz.proto b/computepipe/tests/fuzz/Fuzz.proto
new file mode 100644
index 0000000..31495d8
--- /dev/null
+++ b/computepipe/tests/fuzz/Fuzz.proto
@@ -0,0 +1,21 @@
+syntax = "proto2";
+
+package android.automotive.computepipe.fuzz.proto;
+
+enum PixelFormat {
+ RGB = 0;
+ RGBA = 1;
+ GRAY = 2;
+}
+
+message Frame {
+ required uint32 height = 1;
+ required uint32 width = 2;
+ required PixelFormat format = 3;
+ required uint32 stride = 4;
+ required string buffer = 5;
+}
+
+message PixelMemHandleFuzzerInput {
+ repeated Frame frames = 1;
+}
\ No newline at end of file
diff --git a/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
new file mode 100644
index 0000000..3e98e2a
--- /dev/null
+++ b/computepipe/tests/fuzz/PixelMemHandleFuzzer.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <vndk/hardware_buffer.h>
+
+#include "InputFrame.h"
+#include "PixelFormatUtils.h"
+#include "PixelStreamManager.h"
+#include "gmock/gmock-matchers.h"
+#include "Fuzz.pb.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+namespace android {
+namespace automotive {
+namespace computepipe {
+namespace runner {
+namespace stream_manager {
+namespace {
+
+InputFrame convertToInputFrame(const fuzz::proto::Frame frame) {
+ uint32_t height = frame.height();
+ uint32_t width = frame.width();
+ uint32_t stride = frame.stride();
+ PixelFormat pixelFormat = static_cast<PixelFormat>(frame.format());
+ const uint8_t* data = reinterpret_cast<const uint8_t*>(frame.buffer().c_str());
+ return InputFrame(height, width, pixelFormat, stride, data);
+}
+
+int setFrameDataTest(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+ int bufferId = 10;
+ int streamId = 1;
+ uint64_t timestamp = 100;
+
+ PixelMemHandle memHandle(bufferId, streamId, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
+ InputFrame oldInputFrame = convertToInputFrame(input.frames().Get(0));
+ memHandle.setFrameData(timestamp, oldInputFrame);
+
+ // overwrite frame data with different format and dimensions
+ InputFrame newInputFrame = convertToInputFrame(input.frames().Get(1));
+ memHandle.setFrameData(timestamp, newInputFrame);
+
+ AHardwareBuffer_Desc desc;
+ AHardwareBuffer* buffer = memHandle.getHardwareBuffer();
+ AHardwareBuffer_describe(buffer, &desc);
+ return 0;
+}
+
+bool isValid(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+ for (auto& frame : input.frames()) {
+ uint64_t height = frame.height();
+ uint64_t width = frame.width();
+ uint64_t stride = frame.stride();
+ uint64_t size = frame.buffer().size();
+ if (stride > width * height) {
+ return false;
+ }
+
+ if (height * width != size) {
+ return false;
+ }
+
+ if (height * width == 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// generate guided and mutated frame data for fuzzing
+DEFINE_PROTO_FUZZER(const fuzz::proto::PixelMemHandleFuzzerInput& input) {
+ static PostProcessorRegistration reg = {
+ [](const fuzz::proto::PixelMemHandleFuzzerInput* input, unsigned int seed) {
+ if (input->frames().size() < 2) {
+ return;
+ }
+
+ if (!isValid(*input)) {
+ return;
+ }
+
+ setFrameDataTest(*input);
+ }
+ };
+}
+
+} // namespace
+} // namespace stream_manager
+} // namespace runner
+} // namespace computepipe
+} // namespace automotive
+} // namespace android