patchpanel: Add fuzzer for client

BUG=b:142768280
TEST=run fuzzer

Change-Id: Ic7d96e192cc41cff50eace80e89b5e21ae96b077
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2211637
Tested-by: Garrick Evans <garrick@chromium.org>
Commit-Queue: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
diff --git a/patchpanel/client_fuzzer.cc b/patchpanel/client_fuzzer.cc
new file mode 100644
index 0000000..d15f9a4
--- /dev/null
+++ b/patchpanel/client_fuzzer.cc
@@ -0,0 +1,102 @@
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <base/logging.h>
+#include <dbus/message.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "patchpanel/client.h"
+
+namespace patchpanel {
+
+class Environment {
+ public:
+  Environment() {
+    logging::SetMinLogLevel(logging::LOG_FATAL);  // <- DISABLE LOGGING.
+  }
+};
+
+class FakeObjectProxy : public dbus::ObjectProxy {
+ public:
+  explicit FakeObjectProxy(dbus::Bus* bus)
+      : dbus::ObjectProxy(bus, "svc", dbus::ObjectPath("/obj/path"), 0) {}
+
+  std::unique_ptr<dbus::Response> CallMethodAndBlockWithErrorDetails(
+      dbus::MethodCall* method_call,
+      int timeout_ms,
+      dbus::ScopedDBusError* error) override {
+    return nullptr;
+  }
+
+  std::unique_ptr<dbus::Response> CallMethodAndBlock(
+      dbus::MethodCall* method_call, int timeout_ms) override {
+    return nullptr;
+  }
+
+  void CallMethod(dbus::MethodCall* method_call,
+                  int timeout_ms,
+                  ResponseCallback callback) override {}
+
+  void CallMethodWithErrorResponse(dbus::MethodCall* method_call,
+                                   int timeout_ms,
+                                   ResponseOrErrorCallback callback) override {}
+
+  void CallMethodWithErrorCallback(dbus::MethodCall* method_call,
+                                   int timeout_ms,
+                                   ResponseCallback callback,
+                                   ErrorCallback error_callback) override {}
+
+  void ConnectToSignal(const std::string& interface_name,
+                       const std::string& signal_name,
+                       SignalCallback signal_callback,
+                       OnConnectedCallback on_connected_callback) override {}
+
+  void WaitForServiceToBeAvailable(
+      WaitForServiceToBeAvailableCallback callback) override {}
+
+  void Detach() override {}
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  // static Environment env;
+  dbus::Bus::Options options;
+  scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
+  scoped_refptr<dbus::ObjectProxy> proxy(new FakeObjectProxy(bus.get()));
+  Client client(bus, proxy.get());
+  FuzzedDataProvider provider(data, size);
+
+  while (provider.remaining_bytes() > 0) {
+    client.NotifyArcStartup(provider.ConsumeIntegral<pid_t>());
+    client.NotifyArcVmStartup(provider.ConsumeIntegral<uint32_t>());
+    client.NotifyArcVmShutdown(provider.ConsumeIntegral<uint32_t>());
+    NetworkDevice device;
+    device.set_ifname(provider.ConsumeRandomLengthString(100));
+    device.set_ipv4_addr(provider.ConsumeIntegral<uint32_t>());
+    device.mutable_ipv4_subnet()->set_base_addr(
+        provider.ConsumeIntegral<uint32_t>());
+    device.mutable_ipv4_subnet()->set_prefix_len(
+        provider.ConsumeIntegral<uint32_t>());
+    IPv4Subnet subnet;
+    subnet.set_base_addr(provider.ConsumeIntegral<uint32_t>());
+    subnet.set_prefix_len(provider.ConsumeIntegral<uint32_t>());
+    client.NotifyTerminaVmStartup(provider.ConsumeIntegral<uint32_t>(), &device,
+                                  &subnet);
+    client.NotifyTerminaVmShutdown(provider.ConsumeIntegral<uint32_t>());
+    client.NotifyPluginVmStartup(provider.ConsumeIntegral<uint64_t>(),
+                                 provider.ConsumeIntegral<int>(), &device);
+    client.NotifyPluginVmShutdown(provider.ConsumeIntegral<uint64_t>());
+    // TODO(garrick): Enable the following once the memory leaks in Chrome OS
+    // DBus are resolved.
+    //    client.DefaultVpnRouting(provider.ConsumeIntegral<int>());
+    //    client.RouteOnVpn(provider.ConsumeIntegral<int>());
+    //    client.BypassVpn(provider.ConsumeIntegral<int>());
+    client.ConnectNamespace(provider.ConsumeIntegral<pid_t>(),
+                            provider.ConsumeRandomLengthString(100),
+                            provider.ConsumeBool());
+  }
+  bus->ShutdownAndBlock();
+  return 0;
+}
+
+}  // namespace patchpanel