patchpanel: Add counters_service_fuzzer

BUG=b:160113164
TEST=build and run counters_service_fuzzer

Change-Id: Id83550867505a6d0e84f3fc40f6db1e9cfcc9887
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2593506
Commit-Queue: Jie Jiang <jiejiang@chromium.org>
Tested-by: Jie Jiang <jiejiang@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
Reviewed-by: Garrick Evans <garrick@chromium.org>
diff --git a/patchpanel/BUILD.gn b/patchpanel/BUILD.gn
index b3d6b4f..524a520 100644
--- a/patchpanel/BUILD.gn
+++ b/patchpanel/BUILD.gn
@@ -13,6 +13,7 @@
   ]
   if (use.fuzzer) {
     deps += [
+      ":counters_service_fuzzer",
       ":datapath_fuzzer",
       ":firewall_fuzzer",
       ":multicast_forwarder_fuzzer",
@@ -182,6 +183,16 @@
     sources = [ "firewall_fuzzer.cc" ]
     deps = [ ":libpatchpanel" ]
   }
+
+  executable("counters_service_fuzzer") {
+    configs += [
+      "//common-mk/common_fuzzer",
+      ":target_defaults",
+      ":fuzzing_config",
+    ]
+    sources = [ "counters_service_fuzzer.cc" ]
+    deps = [ ":libpatchpanel" ]
+  }
 }
 
 if (use.test) {
diff --git a/patchpanel/counters_service_fuzzer.cc b/patchpanel/counters_service_fuzzer.cc
new file mode 100644
index 0000000..b2a2188
--- /dev/null
+++ b/patchpanel/counters_service_fuzzer.cc
@@ -0,0 +1,63 @@
+// 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/at_exit.h>
+#include <base/logging.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "patchpanel/counters_service.h"
+#include "patchpanel/datapath.h"
+#include "patchpanel/firewall.h"
+#include "patchpanel/minijailed_process_runner.h"
+
+namespace patchpanel {
+namespace {
+
+class Environment {
+ public:
+  Environment() {
+    logging::SetMinLogLevel(logging::LOGGING_FATAL);  // <- DISABLE LOGGING.
+  }
+  base::AtExitManager at_exit;
+};
+
+class RandomProcessRunner : public MinijailedProcessRunner {
+ public:
+  explicit RandomProcessRunner(FuzzedDataProvider* data_provider)
+      : data_provider_{data_provider} {}
+  RandomProcessRunner(const RandomProcessRunner&) = delete;
+  RandomProcessRunner& operator=(const RandomProcessRunner&) = delete;
+  ~RandomProcessRunner() = default;
+
+  int RunSync(const std::vector<std::string>& argv,
+              bool log_failures,
+              std::string* output) override {
+    if (output) {
+      *output = data_provider_->ConsumeRandomLengthString(10000);
+    }
+    return data_provider_->ConsumeBool();
+  }
+
+ private:
+  FuzzedDataProvider* data_provider_;
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  static Environment env;
+
+  FuzzedDataProvider provider(data, size);
+  RandomProcessRunner runner(&provider);
+  Firewall firewall;
+  Datapath datapath(&runner, &firewall);
+  CountersService counters_svc(&datapath, &runner);
+
+  while (provider.remaining_bytes() > 0) {
+    counters_svc.GetCounters({});
+  }
+
+  return 0;
+}
+
+}  // namespace
+}  // namespace patchpanel