No public description

PiperOrigin-RevId: 599854934
diff --git a/centipede/BUILD b/centipede/BUILD
index 9beecfb..229801c 100644
--- a/centipede/BUILD
+++ b/centipede/BUILD
@@ -56,6 +56,7 @@
         ":centipede_interface",
         ":config_file",
         ":environment_flags",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log:flags",
     ],
 )
@@ -76,6 +77,7 @@
         ":seed_corpus_maker_flags",
         ":seed_corpus_maker_lib",
         ":util",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/flags:flag",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
@@ -92,6 +94,7 @@
         ":logging",
         ":remote_file",
         ":rusage_profiler",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/flags:flag",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
@@ -248,6 +251,7 @@
         ":logging",
         ":remote_file",
         "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/strings:str_format",
@@ -295,6 +299,7 @@
         ":logging",
         ":remote_file",
         ":util",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/flags:flag",
         "@com_google_absl//absl/flags:parse",
         "@com_google_absl//absl/flags:reflection",
@@ -321,6 +326,7 @@
     hdrs = ["rusage_stats.h"],
     visibility = ["//visibility:public"],
     deps = [
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/strings:str_format",
@@ -336,6 +342,7 @@
     deps = [
         ":rusage_stats",
         "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
@@ -443,6 +450,7 @@
     hdrs = ["shared_memory_blob_sequence.h"],
     linkopts = ["-lrt"],  # for shm_open.
     visibility = PUBLIC_API_VISIBILITY,
+    deps = ["@com_google_absl//absl/base:nullability"],
     # don't add any dependencies.
 )
 
@@ -509,6 +517,7 @@
         ":execution_metadata",
         ":knobs",
         ":mutation_input",
+        "@com_google_absl//absl/base:nullability",
     ],
 )
 
@@ -594,6 +603,7 @@
         ":defs",
         ":logging",
         "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
     ] + select({
@@ -708,6 +718,7 @@
         ":shared_memory_blob_sequence",
         ":util",
         ":workdir",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
@@ -796,6 +807,7 @@
         ":util",
         ":workdir",
         "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/container:flat_hash_set",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
@@ -940,6 +952,7 @@
     name = "runner_fork_server",
     srcs = ["runner_fork_server.cc"],
     visibility = PUBLIC_API_VISIBILITY,
+    deps = ["@com_google_absl//absl/base:nullability"],
     alwayslink = 1,  # Otherwise the linker drops the fork server.
 )
 
@@ -1045,7 +1058,7 @@
     linkopts = RUNNER_LINKOPTS,
     linkstatic = True,  # Must be linked statically even when dynamic_mode=on.
     visibility = ["//visibility:public"],
-    deps = RUNNER_DEPS,
+    deps = RUNNER_DEPS + ["@com_google_absl//absl/base:nullability"],
 )
 
 # Same as :centipede_runner_no_main but as a DSO. Experimental.
@@ -1056,7 +1069,7 @@
     linkopts = RUNNER_LINKOPTS,
     linkshared = 1,
     visibility = ["//visibility:public"],
-    deps = RUNNER_DEPS,
+    deps = RUNNER_DEPS + ["@com_google_absl//absl/base:nullability"],
 )
 
 # A full self-contained library archive that external clients should link to
@@ -1069,7 +1082,7 @@
     linkopts = RUNNER_LINKOPTS,
     linkstatic = True,  # Must be linked statically even when dynamic_mode=on.
     visibility = ["//visibility:public"],
-    deps = RUNNER_DEPS,
+    deps = RUNNER_DEPS + ["@com_google_absl//absl/base:nullability"],
 )
 
 # Utilities for seed corpus generation.
@@ -1274,6 +1287,7 @@
     deps = [
         ":logging",
         ":rusage_stats",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/flags:flag",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/synchronization",
@@ -1347,6 +1361,7 @@
         ":test_util",
         ":util",
         ":workdir",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -1496,6 +1511,7 @@
     deps = [
         ":callstack",
         ":defs",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/container:flat_hash_set",
         "@com_google_googletest//:gtest_main",
     ],
@@ -1530,7 +1546,10 @@
 cc_binary(
     name = "command_test_helper",
     srcs = ["command_test_helper.cc"],
-    deps = [":runner_fork_server"],
+    deps = [
+        ":runner_fork_server",
+        "@com_google_absl//absl/base:nullability",
+    ],
 )
 
 cc_test(
@@ -1554,6 +1573,7 @@
     srcs = ["runner_cmp_trace_test.cc"],
     deps = [
         ":runner_cmp_trace",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -1651,6 +1671,7 @@
         ":test_util",
         ":util",
         ":workdir",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_absl//absl/container:flat_hash_set",
         "@com_google_absl//absl/log",
         "@com_google_absl//absl/log:check",
diff --git a/centipede/batch_fuzz_example/BUILD b/centipede/batch_fuzz_example/BUILD
index feae046..cb2e1f0 100644
--- a/centipede/batch_fuzz_example/BUILD
+++ b/centipede/batch_fuzz_example/BUILD
@@ -58,6 +58,7 @@
     srcs = ["customized_centipede_main.cc"],
     deps = [
         ":customized_centipede_lib",
+        "@com_google_absl//absl/base:nullability",
         "@com_google_fuzztest//centipede:centipede_callbacks",
         "@com_google_fuzztest//centipede:centipede_interface",
         "@com_google_fuzztest//centipede:config_file",
diff --git a/centipede/batch_fuzz_example/customized_centipede_main.cc b/centipede/batch_fuzz_example/customized_centipede_main.cc
index cefc91c..3a4a7f0 100644
--- a/centipede/batch_fuzz_example/customized_centipede_main.cc
+++ b/centipede/batch_fuzz_example/customized_centipede_main.cc
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "absl/base/nullability.h"
 #include "./centipede/batch_fuzz_example/customized_centipede.h"
 #include "./centipede/centipede_callbacks.h"
 #include "./centipede/centipede_interface.h"
 #include "./centipede/config_file.h"
 #include "./centipede/environment_flags.h"
 
-int main(int argc, char** argv) {
+int main(int argc, absl::Nonnull<char**> argv) {
   const auto leftover_argv = centipede::config::InitCentipede(argc, argv);
 
   // Reads flags; must happen after ParseCommandLine().
diff --git a/centipede/blob_file_converter.cc b/centipede/blob_file_converter.cc
index 21d560e..0db699a 100644
--- a/centipede/blob_file_converter.cc
+++ b/centipede/blob_file_converter.cc
@@ -17,6 +17,7 @@
 #include <filesystem>  // NOLINT
 #include <string>
 
+#include "absl/base/nullability.h"
 #include "absl/flags/flag.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
@@ -133,7 +134,7 @@
 }  // namespace
 }  // namespace centipede
 
-int main(int argc, char** argv) {
+int main(int argc, absl::Nonnull<char**> argv) {
   (void)centipede::config::InitRuntime(argc, argv);
 
   const std::string in = absl::GetFlag(FLAGS_in);
diff --git a/centipede/byte_array_mutator.h b/centipede/byte_array_mutator.h
index a82f36d..31465b8 100644
--- a/centipede/byte_array_mutator.h
+++ b/centipede/byte_array_mutator.h
@@ -22,6 +22,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/defs.h"
 #include "./centipede/execution_metadata.h"
 #include "./centipede/knobs.h"
@@ -40,7 +41,7 @@
     if (size_ > kMaxEntrySize) __builtin_trap();
     memcpy(bytes_, bytes.data(), bytes.size());
   }
-  const uint8_t *begin() const { return bytes_; }
+  absl::Nonnull<const uint8_t *> begin() const { return bytes_; }
   const uint8_t *end() const { return bytes_ + size_; }
   size_t size() const { return size_; }
   bool operator<(const DictEntry &other) const {
diff --git a/centipede/callstack_test.cc b/centipede/callstack_test.cc
index 57bf050..ee9b5e6 100644
--- a/centipede/callstack_test.cc
+++ b/centipede/callstack_test.cc
@@ -22,6 +22,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/nullability.h"
 #include "absl/container/flat_hash_set.h"
 #include "./centipede/defs.h"
 
@@ -76,7 +77,7 @@
       PC, reinterpret_cast<uintptr_t>(__builtin_frame_address(0)))
 
 // Don't let the compiler be too smart.
-static inline void BreakOptimization(const void *arg) {
+static inline void BreakOptimization(absl::Nullable<const void *> arg) {
   __asm__ __volatile__("" : : "r"(arg) : "memory");
 }
 
diff --git a/centipede/centipede.cc b/centipede/centipede.cc
index b77e5b4..08bb8eb 100644
--- a/centipede/centipede.cc
+++ b/centipede/centipede.cc
@@ -60,6 +60,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/const_init.h"  // NOLINT
+#include "absl/base/nullability.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
@@ -342,10 +343,11 @@
   return num_added_pairs;
 }
 
-bool Centipede::RunBatch(const std::vector<ByteArray> &input_vec,
-                         BlobFileWriter *corpus_file,
-                         BlobFileWriter *features_file,
-                         BlobFileWriter *unconditional_features_file) {
+bool Centipede::RunBatch(
+    const std::vector<ByteArray> &input_vec,
+    absl::Nullable<BlobFileWriter *> corpus_file,
+    absl::Nullable<BlobFileWriter *> features_file,
+    absl::Nullable<BlobFileWriter *> unconditional_features_file) {
   BatchResult batch_result;
   bool success = ExecuteAndReportCrash(env_.binary, input_vec, batch_result);
   CHECK_EQ(input_vec.size(), batch_result.results().size());
diff --git a/centipede/centipede.h b/centipede/centipede.h
index 63bbcd3..3504848 100644
--- a/centipede/centipede.h
+++ b/centipede/centipede.h
@@ -1,4 +1,3 @@
-#include "./centipede/binary_info.h"
 // Copyright 2022 The Centipede Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,7 +20,9 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/time/time.h"
+#include "./centipede/binary_info.h"
 #include "./centipede/blob_file.h"
 #include "./centipede/centipede_callbacks.h"
 #include "./centipede/command.h"
@@ -77,8 +78,9 @@
   // Returns true if new features were observed.
   // Post-condition: `batch_result.results.size()` == `input_vec.size()`.
   bool RunBatch(const std::vector<ByteArray> &input_vec,
-                BlobFileWriter *corpus_file, BlobFileWriter *features_file,
-                BlobFileWriter *unconditional_features_file);
+                absl::Nullable<BlobFileWriter *> corpus_file,
+                absl::Nullable<BlobFileWriter *> features_file,
+                absl::Nullable<BlobFileWriter *> unconditional_features_file);
   // Loads seed inputs from the user callbacks.
   void LoadSeedInputs();
   // Loads a shard `shard_index` from `load_env.workdir`.
diff --git a/centipede/centipede_callbacks.h b/centipede/centipede_callbacks.h
index 955d272..14d35a8 100644
--- a/centipede/centipede_callbacks.h
+++ b/centipede/centipede_callbacks.h
@@ -21,6 +21,7 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/log/check.h"
 #include "./centipede/binary_info.h"
 #include "./centipede/byte_array_mutator.h"
@@ -198,7 +199,7 @@
                            const Environment &env)
       : factory_(factory), callbacks_(factory_.create(env)) {}
   ~ScopedCentipedeCallbacks() { factory_.destroy(callbacks_); }
-  CentipedeCallbacks *callbacks() { return callbacks_; }
+  absl::Nonnull<CentipedeCallbacks *> callbacks() { return callbacks_; }
 
  private:
   CentipedeCallbacksFactory &factory_;
diff --git a/centipede/centipede_main.cc b/centipede/centipede_main.cc
index 311e773..7ae8864 100644
--- a/centipede/centipede_main.cc
+++ b/centipede/centipede_main.cc
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "absl/base/nullability.h"
 #include "./centipede/centipede_callbacks.h"
 #include "./centipede/centipede_default_callbacks.h"
 #include "./centipede/centipede_interface.h"
 #include "./centipede/config_file.h"
 #include "./centipede/environment_flags.h"
 
-int main(int argc, char** argv) {
+int main(int argc, absl::Nonnull<char**> argv) {
   const auto leftover_argv = centipede::config::InitCentipede(argc, argv);
 
   const auto env = centipede::CreateEnvironmentFromFlags(leftover_argv);
diff --git a/centipede/centipede_test.cc b/centipede/centipede_test.cc
index 21065b6..db528a4 100644
--- a/centipede/centipede_test.cc
+++ b/centipede/centipede_test.cc
@@ -26,6 +26,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/nullability.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
@@ -124,7 +125,9 @@
 class MockFactory : public CentipedeCallbacksFactory {
  public:
   explicit MockFactory(CentipedeCallbacks &cb) : cb_(cb) {}
-  CentipedeCallbacks *create(const Environment &env) override { return &cb_; }
+  absl::Nonnull<CentipedeCallbacks *> create(const Environment &env) override {
+    return &cb_;
+  }
   void destroy(CentipedeCallbacks *cb) override { EXPECT_EQ(cb, &cb_); }
 
  private:
diff --git a/centipede/command_test_helper.cc b/centipede/command_test_helper.cc
index 73d95d2..cf4c82a 100644
--- a/centipede/command_test_helper.cc
+++ b/centipede/command_test_helper.cc
@@ -19,8 +19,10 @@
 #include <cstdlib>
 #include <cstring>
 
+#include "absl/base/nullability.h"
+
 // A binary linked with the fork server that exits/crashes in different ways.
-int main(int argc, char **argv) {
+int main(int argc, absl::Nonnull<char **> argv) {
   assert(argc == 2);
   printf("Got input: %s", argv[1]);
   fflush(stdout);
diff --git a/centipede/config_file.cc b/centipede/config_file.cc
index 01fa635..d560361 100644
--- a/centipede/config_file.cc
+++ b/centipede/config_file.cc
@@ -22,6 +22,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/parse.h"
@@ -230,7 +231,7 @@
   return path;
 }
 
-std::vector<std::string> InitCentipede(int argc, char** argv) {
+std::vector<std::string> InitCentipede(int argc, absl::Nonnull<char**> argv) {
   std::vector<std::string> leftover_argv;
 
   // main_runtime_init() is allowed to remove recognized flags from `argv`, so
diff --git a/centipede/config_file.h b/centipede/config_file.h
index 7455c9b..9653e9a 100644
--- a/centipede/config_file.h
+++ b/centipede/config_file.h
@@ -21,6 +21,8 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/nullability.h"
+
 // TODO(ussuri): Move implementation-only functions to .cc.
 
 namespace centipede::config {
@@ -98,7 +100,8 @@
 //   and saves it to --save_config (or --update_config), if any.
 // - Logs the final resolved config.
 // - Returns the leftover positional command line arguments in
-[[nodiscard]] std::vector<std::string> InitCentipede(int argc, char** argv);
+[[nodiscard]] std::vector<std::string> InitCentipede(
+    int argc, absl::Nonnull<char**> argv);
 
 }  // namespace centipede::config
 
diff --git a/centipede/minimize_crash_test.cc b/centipede/minimize_crash_test.cc
index c4911de..28d704c 100644
--- a/centipede/minimize_crash_test.cc
+++ b/centipede/minimize_crash_test.cc
@@ -22,6 +22,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/nullability.h"
 #include "./centipede/centipede_callbacks.h"
 #include "./centipede/defs.h"
 #include "./centipede/environment.h"
@@ -68,7 +69,7 @@
 // Factory that creates/destroys MinimizerMock.
 class MinimizerMockFactory : public CentipedeCallbacksFactory {
  public:
-  CentipedeCallbacks *create(const Environment &env) override {
+  absl::Nonnull<CentipedeCallbacks *> create(const Environment &env) override {
     return new MinimizerMock(env);
   }
   void destroy(CentipedeCallbacks *cb) override { delete cb; }
diff --git a/centipede/puzzles/deep_recursion.cc b/centipede/puzzles/deep_recursion.cc
index b6d7cb7..bd6fb64 100644
--- a/centipede/puzzles/deep_recursion.cc
+++ b/centipede/puzzles/deep_recursion.cc
@@ -22,12 +22,14 @@
 #include <cstddef>
 #include <cstdint>
 
+#include "absl/base/nullability.h"
+
 // Set the stack size to something small (64K).
 static struct rlimit rlim = {1 << 16, 1 << 16};
 static int unused = setrlimit(RLIMIT_STACK, &rlim);
 
 // Don't let the compiler be too smart.
-static inline void BreakOptimization(const void *arg) {
+static inline void BreakOptimization(absl::Nonnull<const void *> arg) {
   __asm__ __volatile__("" : : "r"(arg) : "memory");
 }
 
diff --git a/centipede/puzzles/puzzle.bzl b/centipede/puzzles/puzzle.bzl
index 3be0242..69ee1f1 100644
--- a/centipede/puzzles/puzzle.bzl
+++ b/centipede/puzzles/puzzle.bzl
@@ -25,6 +25,9 @@
 
     centipede_fuzz_target(
         name = name,
+        deps = [
+            "@com_google_absl//absl/base:nullability",
+        ],
     )
 
     # We test every puzzle with two different seeds so that the result is more
diff --git a/centipede/remote_file.cc b/centipede/remote_file.cc
index 07b7022..3f8cd79 100644
--- a/centipede/remote_file.cc
+++ b/centipede/remote_file.cc
@@ -28,6 +28,7 @@
 #include <vector>
 
 #include "absl/base/attributes.h"
+#include "absl/base/nullability.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
 #include "./centipede/defs.h"
@@ -54,19 +55,20 @@
   CHECK(!error) << VV(path) << VV(error);
 }
 
-ABSL_ATTRIBUTE_WEAK RemoteFile *RemoteFileOpen(std::string_view path,
-                                               const char *mode) {
+ABSL_ATTRIBUTE_WEAK absl::Nullable<RemoteFile *> RemoteFileOpen(
+    std::string_view path, const char *mode) {
   CHECK(!path.empty());
   FILE *f = std::fopen(path.data(), mode);
   return reinterpret_cast<RemoteFile *>(f);
 }
 
-ABSL_ATTRIBUTE_WEAK void RemoteFileClose(RemoteFile *f) {
+ABSL_ATTRIBUTE_WEAK void RemoteFileClose(absl::Nonnull<RemoteFile *> f) {
   CHECK(f != nullptr);
   std::fclose(reinterpret_cast<FILE *>(f));
 }
 
-ABSL_ATTRIBUTE_WEAK void RemoteFileAppend(RemoteFile *f, const ByteArray &ba) {
+ABSL_ATTRIBUTE_WEAK void RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
+                                          const ByteArray &ba) {
   CHECK(f != nullptr);
   auto *file = reinterpret_cast<FILE *>(f);
   constexpr auto elt_size = sizeof(ba[0]);
@@ -84,7 +86,8 @@
   RemoteFileAppend(f, contents_ba);
 }
 
-ABSL_ATTRIBUTE_WEAK void RemoteFileRead(RemoteFile *f, ByteArray &ba) {
+ABSL_ATTRIBUTE_WEAK void RemoteFileRead(absl::Nonnull<RemoteFile *> f,
+                                        ByteArray &ba) {
   CHECK(f != nullptr);
   auto *file = reinterpret_cast<FILE *>(f);
   std::fseek(file, 0, SEEK_END);  // seek to end
@@ -100,7 +103,7 @@
 
 // Does not need weak attribute as the implementation depends on
 // RemoteFileRead(RemoteFile *, ByteArray).
-void RemoteFileRead(RemoteFile *f, std::string &contents) {
+void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents) {
   CHECK(f != nullptr);
   ByteArray contents_ba;
   RemoteFileRead(f, contents_ba);
diff --git a/centipede/remote_file.h b/centipede/remote_file.h
index b63a1e0..1b4a59a 100644
--- a/centipede/remote_file.h
+++ b/centipede/remote_file.h
@@ -28,6 +28,7 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/defs.h"
 #ifndef CENTIPEDE_DISABLE_RIEGELI
 #include "riegeli/bytes/reader.h"
@@ -41,22 +42,23 @@
 
 // Opens a (potentially remote) file 'file_path' and returns a handle to it.
 // Supported modes: "r", "a", "w", same as in C FILE API.
-RemoteFile *RemoteFileOpen(std::string_view file_path, const char *mode);
+absl::Nullable<RemoteFile *> RemoteFileOpen(std::string_view file_path,
+                                            const char *mode);
 
 // Closes the file previously opened by RemoteFileOpen.
-void RemoteFileClose(RemoteFile *f);
+void RemoteFileClose(absl::Nonnull<RemoteFile *> f);
 
 // Appends bytes from 'ba' to 'f'.
-void RemoteFileAppend(RemoteFile *f, const ByteArray &ba);
+void RemoteFileAppend(absl::Nonnull<RemoteFile *> f, const ByteArray &ba);
 
 // Appends characters from 'contents' to 'f'.
 void RemoteFileAppend(RemoteFile *f, const std::string &contents);
 
 // Reads all current contents of 'f' into 'ba'.
-void RemoteFileRead(RemoteFile *f, ByteArray &ba);
+void RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba);
 
 // Reads all current contents of 'f' into 'contents'.
-void RemoteFileRead(RemoteFile *f, std::string &contents);
+void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents);
 
 // Creates a (potentially remote) directory 'dir_path'.
 // No-op if the directory already exists.
diff --git a/centipede/runner.cc b/centipede/runner.cc
index 4e1ab3f..eea6504 100644
--- a/centipede/runner.cc
+++ b/centipede/runner.cc
@@ -45,6 +45,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/byte_array_mutator.h"
 #include "./centipede/defs.h"
 #include "./centipede/execution_metadata.h"
@@ -728,7 +729,7 @@
 
 // Dumps the pc table to `output_path`.
 // Requires that state.main_object is already computed.
-static void DumpPcTable(const char *output_path) {
+static void DumpPcTable(absl::Nonnull<const char *> output_path) {
   PrintErrorAndExitIf(!state.main_object.IsSet(), "main_object is not set");
   FILE *output_file = fopen(output_path, "w");
   PrintErrorAndExitIf(output_file == nullptr, "can't open output file");
@@ -744,7 +745,7 @@
 
 // Dumps the control-flow table to `output_path`.
 // Requires that state.main_object is already computed.
-static void DumpCfTable(const char *output_path) {
+static void DumpCfTable(absl::Nonnull<const char *> output_path) {
   PrintErrorAndExitIf(!state.main_object.IsSet(), "main_object is not set");
   FILE *output_file = fopen(output_path, "w");
   PrintErrorAndExitIf(output_file == nullptr, "can't open output file");
@@ -760,7 +761,7 @@
 
 // Dumps a DsoTable as a text file. Each line contains the file path and the
 // number of instrumented PCs.
-static void DumpDsoTable(const char *output_path) {
+static void DumpDsoTable(absl::Nonnull<const char *> output_path) {
   FILE *output_file = fopen(output_path, "w");
   RunnerCheck(output_file != nullptr, "DumpDsoTable: can't open output file");
   DsoTable dso_table = state.sancov_objects.CreateDsoTable();
@@ -1074,7 +1075,8 @@
 }  // namespace centipede
 
 extern "C" int LLVMFuzzerRunDriver(
-    int *argc, char ***argv, FuzzerTestOneInputCallback test_one_input_cb) {
+    absl::Nonnull<int *> argc, absl::Nonnull<char ***> argv,
+    FuzzerTestOneInputCallback test_one_input_cb) {
   if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(argc, argv);
   return RunnerMain(*argc, *argv,
                     *centipede::CreateLegacyRunnerCallbacks(
@@ -1105,7 +1107,8 @@
   centipede::state.run_time_flags.timeout_per_input = timeout_per_input;
 }
 
-extern "C" __attribute__((weak)) const char *CentipedeGetRunnerFlags() {
+extern "C" __attribute__((weak)) absl::Nullable<const char *>
+CentipedeGetRunnerFlags() {
   if (const char *runner_flags_env = getenv("CENTIPEDE_RUNNER_FLAGS"))
     return strdup(runner_flags_env);
   return nullptr;
diff --git a/centipede/runner.h b/centipede/runner.h
index 73b74d7..9a22fb3 100644
--- a/centipede/runner.h
+++ b/centipede/runner.h
@@ -26,6 +26,7 @@
 #include <cstdlib>
 
 #include "absl/base/const_init.h"
+#include "absl/base/nullability.h"
 #include "absl/numeric/bits.h"
 #include "./centipede/byte_array_mutator.h"
 #include "./centipede/callstack.h"
@@ -169,7 +170,7 @@
 
   // Returns true iff `flag` is present.
   // Typical usage: pass ":some_flag:", i.e. the flag name surrounded with ':'.
-  bool HasFlag(const char *flag) const {
+  bool HasFlag(absl::Nonnull<const char *> flag) const {
     if (!centipede_runner_flags) return false;
     return strstr(centipede_runner_flags, flag) != nullptr;
   }
@@ -177,7 +178,8 @@
   // If a flag=value pair is present, returns value,
   // otherwise returns `default_value`.
   // Typical usage: pass ":some_flag=".
-  uint64_t HasIntFlag(const char *flag, uint64_t default_value) const {
+  uint64_t HasIntFlag(absl::Nonnull<const char *> flag,
+                      uint64_t default_value) const {
     if (!centipede_runner_flags) return default_value;
     const char *beg = strstr(centipede_runner_flags, flag);
     if (!beg) return default_value;
@@ -188,7 +190,8 @@
   // The result is obtained by calling strndup, so make sure to save
   // it in `this` to avoid a leak.
   // Typical usage: pass ":some_flag=".
-  const char *GetStringFlag(const char *flag) const {
+  absl::Nullable<const char *> GetStringFlag(
+      absl::Nonnull<const char *> flag) const {
     if (!centipede_runner_flags) return nullptr;
     // Extract "value" from ":flag=value:" inside centipede_runner_flags.
     const char *beg = strstr(centipede_runner_flags, flag);
diff --git a/centipede/runner_cmp_trace_test.cc b/centipede/runner_cmp_trace_test.cc
index 2e608f4..e3523a3 100644
--- a/centipede/runner_cmp_trace_test.cc
+++ b/centipede/runner_cmp_trace_test.cc
@@ -20,6 +20,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/nullability.h"
 
 namespace centipede {
 namespace {
@@ -35,7 +36,8 @@
   return res;
 }
 
-std::vector<uint8_t> TwoArraysToByteVector(const uint8_t *a, const uint8_t *b,
+std::vector<uint8_t> TwoArraysToByteVector(absl::Nonnull<const uint8_t *> a,
+                                           absl::Nonnull<const uint8_t *> b,
                                            size_t size) {
   std::vector<uint8_t> res;
   res.insert(res.begin(), a, a + size);
diff --git a/centipede/runner_dl_info.cc b/centipede/runner_dl_info.cc
index caa5927..4e8a3a1 100644
--- a/centipede/runner_dl_info.cc
+++ b/centipede/runner_dl_info.cc
@@ -24,6 +24,7 @@
 #include <cstdio>
 #include <cstring>
 
+#include "absl/base/nullability.h"
 #include "./centipede/runner_utils.h"
 
 namespace centipede {
@@ -40,7 +41,8 @@
   DlInfo &result;
 };
 
-bool StringEndsWithSuffix(const char *string, const char *suffix) {
+bool StringEndsWithSuffix(const char *string,
+                          absl::Nonnull<const char *> suffix) {
   const char *pos = strstr(string, suffix);
   if (pos == nullptr) return false;
   return pos == string + strlen(string) - strlen(suffix);
@@ -51,7 +53,7 @@
 constexpr bool kDlDebug = false;  // we may want to make it a runtime flag.
 
 // Returns the size of the DL represented by `info`.
-size_t DlSize(struct dl_phdr_info *info) {
+size_t DlSize(absl::Nonnull<struct dl_phdr_info *> info) {
   size_t size = 0;
   // Iterate program headers.
   for (int j = 0; j < info->dlpi_phnum; ++j) {
@@ -88,8 +90,8 @@
 // nullptr`. The code assumes that the main binary is the first one to be
 // iterated on. If the desired library is found, sets result.start_address and
 // result.size, otherwise leaves result unchanged.
-int DlIteratePhdrCallback(struct dl_phdr_info *info, size_t size,
-                          void *param_voidptr) {
+int DlIteratePhdrCallback(absl::Nonnull<struct dl_phdr_info *> info,
+                          size_t size, absl::Nonnull<void *> param_voidptr) {
   const DlCallbackParam *param = static_cast<DlCallbackParam *>(param_voidptr);
   DlInfo &result = param->result;
   RunnerCheck(!result.IsSet(), "result is already set");
@@ -138,8 +140,9 @@
 // See man dl_iterate_phdr.
 // `param_voidptr` is cast to a `DlCallbackParam *param`.
 // Looks for the dynamic library who's address range contains `param->pc`.
-int DlIteratePhdrPCCallback(struct dl_phdr_info *info, size_t unused,
-                            void *param_voidptr) {
+int DlIteratePhdrPCCallback(absl::Nonnull<struct dl_phdr_info *> info,
+                            size_t unused,
+                            absl::Nonnull<void *> param_voidptr) {
   const DlCallbackParam *param = static_cast<DlCallbackParam *>(param_voidptr);
   DlInfo &result = param->result;
   if (param->pc < info->dlpi_addr) return 0;  // wrong DSO.
@@ -161,7 +164,7 @@
 
 }  // namespace
 
-DlInfo GetDlInfo(const char *dl_path_suffix) {
+DlInfo GetDlInfo(absl::Nullable<const char *> dl_path_suffix) {
   DlInfo result;
   result.Clear();
   DlCallbackParam callback_param = {dl_path_suffix, /*pc=*/0, result};
diff --git a/centipede/runner_dl_info.h b/centipede/runner_dl_info.h
index 53b5fc9..7493d04 100644
--- a/centipede/runner_dl_info.h
+++ b/centipede/runner_dl_info.h
@@ -18,6 +18,7 @@
 #include <cstdint>
 #include <cstring>
 
+#include "absl/base/nullability.h"
 #include "./centipede/defs.h"
 
 namespace centipede {
@@ -45,7 +46,7 @@
 // Returns DlInfo for the dynamic library who's exact path is `dl_path_suffix`.
 // If `dl_path_suffix` is `nullptr`, returns DlInfo for the main binary.
 // If the required library is not found, returns empty DlInfo (`!IsSet()`).
-DlInfo GetDlInfo(const char *dl_path_suffix);
+DlInfo GetDlInfo(absl::Nullable<const char *> dl_path_suffix);
 
 // Returns DlInfo for the dynamic library that contains `pc`.
 DlInfo GetDlInfo(uintptr_t pc);
diff --git a/centipede/runner_fork_server.cc b/centipede/runner_fork_server.cc
index 78b33b1..5c790e4 100644
--- a/centipede/runner_fork_server.cc
+++ b/centipede/runner_fork_server.cc
@@ -60,17 +60,19 @@
 #include <cstdlib>
 #include <cstring>
 
+#include "absl/base/nullability.h"
+
 namespace centipede {
 
 // Writes a C string to stderr when debugging, no-op otherwise.
-void Log(const char *str) {
+void Log(absl::Nonnull<const char *> str) {
   // Uncomment these lines to debug.
   // (void)write(STDERR_FILENO, str, strlen(str));
   // fsync(STDERR_FILENO);
 }
 
 // Maybe writes the `reason` to stderr; then calls _exit.
-void Exit(const char *reason) {
+void Exit(absl::Nonnull<const char *> reason) {
   Log(reason);
   _exit(0);  // The exit code does not matter, it won't be checked anyway.
 }
@@ -91,7 +93,7 @@
 }
 
 // Gets a zero-terminated string matching the environment `key` (ends with '=').
-const char *GetOneEnv(const char *key) {
+absl::Nullable<const char *> GetOneEnv(absl::Nonnull<const char *> key) {
   size_t key_len = strlen(key);
   if (env_size < key_len) return nullptr;
   bool in_the_beginning_of_key = true;
diff --git a/centipede/runner_interceptors.cc b/centipede/runner_interceptors.cc
index 62776b8..864f540 100644
--- a/centipede/runner_interceptors.cc
+++ b/centipede/runner_interceptors.cc
@@ -20,6 +20,7 @@
 #include <cstdint>
 #include <cstring>
 
+#include "absl/base/nullability.h"
 #include "./centipede/runner.h"
 
 using centipede::tls;
@@ -48,7 +49,7 @@
 // Calls the actual start_routine and returns its results.
 // Performs custom actions before and after start_routine().
 // `arg` is a `ThreadCreateArgs *` with the actual pthread_create() args.
-void *MyThreadStart(void *arg) {
+void *MyThreadStart(absl::Nonnull<void *> arg) {
   auto *args_orig_ptr = static_cast<ThreadCreateArgs *>(arg);
   auto args = *args_orig_ptr;
   delete args_orig_ptr;  // allocated in the pthread_create wrapper.
@@ -153,8 +154,10 @@
 
 // pthread_create interceptor.
 // Calls real pthread_create, but wraps the start_routine() in MyThreadStart.
-extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
-                              void *(*start_routine)(void *), void *arg) {
+extern "C" int pthread_create(absl::Nonnull<pthread_t *> thread,
+                              absl::Nullable<const pthread_attr_t *> attr,
+                              void *(*start_routine)(void *),
+                              absl::Nullable<void *> arg) {
   // Wrap the arguments. Will be deleted in MyThreadStart.
   auto *wrapped_args = new ThreadCreateArgs{start_routine, arg};
   // Run the actual pthread_create.
diff --git a/centipede/runner_interface.h b/centipede/runner_interface.h
index c2a071b..f2090d4 100644
--- a/centipede/runner_interface.h
+++ b/centipede/runner_interface.h
@@ -23,6 +23,7 @@
 #include <memory>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/defs.h"
 #include "./centipede/mutation_input.h"
 
@@ -40,7 +41,8 @@
 // https://llvm.org/docs/LibFuzzer.html.
 extern "C" {
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+__attribute__((weak)) int LLVMFuzzerInitialize(absl::Nonnull<int *> argc,
+                                               absl::Nonnull<char ***> argv);
 __attribute__((weak)) size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
                                                      size_t max_size,
                                                      unsigned int seed);
@@ -51,7 +53,8 @@
 
 // https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library
 extern "C" int LLVMFuzzerRunDriver(
-    int *argc, char ***argv, FuzzerTestOneInputCallback test_one_input_cb);
+    absl::Nonnull<int *> argc, absl::Nonnull<char ***> argv,
+    FuzzerTestOneInputCallback test_one_input_cb);
 
 // This interface can be used to detect presence of Centipede in the binary.
 // Also pretend we are LibFuzzer for compatibility.
@@ -76,7 +79,7 @@
 //
 // It should return either a nullptr or a constant string that is valid
 // throughout the entire process life-time.
-extern "C" const char *CentipedeGetRunnerFlags();
+extern "C" absl::Nullable<const char *> CentipedeGetRunnerFlags();
 
 // Prepares to run a batch of test executions that ends with calling
 // `CentipedeEndExecutionBatch`.
diff --git a/centipede/runner_main.cc b/centipede/runner_main.cc
index f2343cf..b407ed4 100644
--- a/centipede/runner_main.cc
+++ b/centipede/runner_main.cc
@@ -12,8 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "absl/base/nullability.h"
 #include "./centipede/runner_interface.h"
 
-int main(int argc, char **argv) {
+int main(int argc, absl::Nonnull<char **> argv) {
   return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput);
 }
diff --git a/centipede/runner_sancov.cc b/centipede/runner_sancov.cc
index 0c564c8..30bb2fe 100644
--- a/centipede/runner_sancov.cc
+++ b/centipede/runner_sancov.cc
@@ -21,6 +21,7 @@
 #include <cstdint>
 #include <cstdio>
 
+#include "absl/base/nullability.h"
 #include "./centipede/feature.h"
 #include "./centipede/int_utils.h"
 #include "./centipede/pc_info.h"
@@ -163,7 +164,8 @@
 // When called from the same DSO, the arguments will always be the same.
 // If a different DSO calls this function, it will have different arguments.
 // We currently do not support more than one sancov-instrumented DSO.
-void __sanitizer_cov_pcs_init(const PCInfo *beg, const PCInfo *end) {
+void __sanitizer_cov_pcs_init(absl::Nonnull<const PCInfo *> beg,
+                              const PCInfo *end) {
   state.sancov_objects.PCInfoInit(beg, end);
 }
 
@@ -290,14 +292,15 @@
 }
 
 // This function is called at the DSO init time.
-void __sanitizer_cov_trace_pc_guard_init(PCGuard *start, PCGuard *stop) {
+void __sanitizer_cov_trace_pc_guard_init(absl::Nonnull<PCGuard *> start,
+                                         PCGuard *stop) {
   state.sancov_objects.PCGuardInit(start, stop);
   UpdatePcCounterSetSizeAligned(state.sancov_objects.NumInstrumentedPCs());
 }
 
 // This function is called on every instrumented edge.
 NO_SANITIZE
-void __sanitizer_cov_trace_pc_guard(PCGuard *guard) {
+void __sanitizer_cov_trace_pc_guard(absl::Nonnull<PCGuard *> guard) {
   // This function may be called very early during the DSO initialization,
   // before the values of `*guard` are initialized to non-zero.
   // But it will immidiately return bacause state.run_time_flags.use_pc_features
diff --git a/centipede/runner_sancov_object.cc b/centipede/runner_sancov_object.cc
index 37af833..a6338ca 100644
--- a/centipede/runner_sancov_object.cc
+++ b/centipede/runner_sancov_object.cc
@@ -24,6 +24,7 @@
 #include <functional>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/foreach_nonzero.h"
 #include "./centipede/pc_info.h"
 #include "./centipede/runner_dl_info.h"
@@ -31,7 +32,8 @@
 
 namespace centipede {
 
-void SanCovObjectArray::PCGuardInit(PCGuard *start, PCGuard *stop) {
+void SanCovObjectArray::PCGuardInit(absl::Nonnull<PCGuard *> start,
+                                    PCGuard *stop) {
   // Ignore repeated calls with the same arguments.
   if (size_ != 0 && objects_[size_ - 1].pc_guard_start == start) return;
   RunnerCheck(size_ < kMaxSize, "too many sancov objects");
@@ -57,7 +59,7 @@
   sancov_object.inline_8bit_counters_stop = inline_8bit_counters_stop;
 }
 
-void SanCovObjectArray::PCInfoInit(const PCInfo *pcs_beg,
+void SanCovObjectArray::PCInfoInit(absl::Nonnull<const PCInfo *> pcs_beg,
                                    const PCInfo *pcs_end) {
   const char *called_early =
       "__sanitizer_cov_pcs_init is called before either of "
diff --git a/centipede/runner_sancov_object.h b/centipede/runner_sancov_object.h
index 1c6dc56..3fa6ad9 100644
--- a/centipede/runner_sancov_object.h
+++ b/centipede/runner_sancov_object.h
@@ -20,6 +20,7 @@
 #include <functional>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/pc_info.h"
 #include "./centipede/runner_dl_info.h"
 
@@ -50,10 +51,10 @@
 class SanCovObjectArray {
  public:
   // To be called in __sanitizer_cov_trace_pc_guard_init.
-  void PCGuardInit(PCGuard *start, PCGuard *stop);
+  void PCGuardInit(absl::Nonnull<PCGuard *> start, PCGuard *stop);
 
   // To be called in __sanitizer_cov_pcs_init.
-  void PCInfoInit(const PCInfo *pcs_beg, const PCInfo *pcs_end);
+  void PCInfoInit(absl::Nonnull<const PCInfo *> pcs_beg, const PCInfo *pcs_end);
 
   // To be called in __sanitizer_cov_cfs_init.
   void CFSInit(const uintptr_t *cfs_beg, const uintptr_t *cfs_end);
diff --git a/centipede/runner_utils.cc b/centipede/runner_utils.cc
index f47d92e..c1a2b9c 100644
--- a/centipede/runner_utils.cc
+++ b/centipede/runner_utils.cc
@@ -20,9 +20,11 @@
 #include <cstdio>
 #include <cstdlib>
 
+#include "absl/base/nullability.h"
+
 namespace centipede {
 
-void PrintErrorAndExitIf(bool condition, const char *error) {
+void PrintErrorAndExitIf(bool condition, absl::Nonnull<const char *> error) {
   if (!condition) return;
   fprintf(stderr, "error: %s\n", error);
   exit(1);
diff --git a/centipede/runner_utils.h b/centipede/runner_utils.h
index 85815ec..42cada9 100644
--- a/centipede/runner_utils.h
+++ b/centipede/runner_utils.h
@@ -17,15 +17,17 @@
 
 #include <cstdint>
 
+#include "absl/base/nullability.h"
+
 namespace centipede {
 
 // If `condition` prints `error` and calls exit(1).
 // TODO(kcc): change all uses of PrintErrorAndExitIf() to RunnerCheck()
 // as it is a more common pattern.
-void PrintErrorAndExitIf(bool condition, const char *error);
+void PrintErrorAndExitIf(bool condition, absl::Nonnull<const char *> error);
 
 // A rough equivalent of "CHECK(condition) << error;".
-inline void RunnerCheck(bool condition, const char *error) {
+inline void RunnerCheck(bool condition, absl::Nonnull<const char *> error) {
   PrintErrorAndExitIf(!condition, error);
 }
 
diff --git a/centipede/rusage_profiler.cc b/centipede/rusage_profiler.cc
index 69b8748..1d2f86f 100644
--- a/centipede/rusage_profiler.cc
+++ b/centipede/rusage_profiler.cc
@@ -29,6 +29,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/const_init.h"
+#include "absl/base/nullability.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
@@ -180,7 +181,7 @@
  public:
   ProfileReportGenerator(                                     //
       const std::deque<RUsageProfiler::Snapshot>& snapshots,  //
-      RUsageProfiler::ReportSink* report_sink)
+      absl::Nonnull<RUsageProfiler::ReportSink*> report_sink)
       : snapshots_{snapshots}, report_sink_{report_sink} {
     for (const auto& snapshot : snapshots_) {
       timing_low_ = RUsageTiming::LowWater(  //
@@ -530,7 +531,8 @@
   GenerateReport(&report_logger);
 }
 
-void RUsageProfiler::GenerateReport(ReportSink* report_sink) const {
+void RUsageProfiler::GenerateReport(
+    absl::Nonnull<ReportSink*> report_sink) const {
   absl::ReaderMutexLock lock{&mutex_};
   // Prevent interleaved reports from multiple concurrent RUsageProfilers.
   ABSL_CONST_INIT static absl::Mutex report_generation_mutex_{absl::kConstInit};
diff --git a/centipede/rusage_profiler.h b/centipede/rusage_profiler.h
index bc74298..42b5924 100644
--- a/centipede/rusage_profiler.h
+++ b/centipede/rusage_profiler.h
@@ -215,6 +215,7 @@
 #include <string>
 #include <string_view>
 
+#include "absl/base/nullability.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/strings/str_cat.h"  // IWYU pragma: keep
 #include "absl/synchronization/mutex.h"
@@ -228,7 +229,8 @@
 // TODO(ussuri): Switch to absl::SourceLocation or std::source_location.
 struct SourceLocation {
   explicit SourceLocation() = default;
-  SourceLocation(const char* file, int line) : file{file}, line{line} {}
+  SourceLocation(absl::Nonnull<const char*> file, int line)
+      : file{file}, line{line} {}
 
   const char* const file = "<unknown>";
   const int line = 0;
@@ -390,7 +392,7 @@
   // Prints to `sink` a report consisting of chronological charts for each of
   // the tracked metrics recorded since this profiler's construction up to this
   // point.
-  void GenerateReport(ReportSink* report_sink) const;
+  void GenerateReport(absl::Nonnull<ReportSink*> report_sink) const;
 
   // Logs the report returned by GenerateReport(). The log message's source
   // location is set to `location`: as a rule of thumb, pass
diff --git a/centipede/rusage_stats.cc b/centipede/rusage_stats.cc
index a71f5fe..c6557ab 100644
--- a/centipede/rusage_stats.cc
+++ b/centipede/rusage_stats.cc
@@ -31,6 +31,7 @@
 #include <string>
 #include <thread>  // NOLINT
 
+#include "absl/base/nullability.h"
 #include "absl/log/check.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
@@ -116,7 +117,8 @@
 //                      Read values from /proc/* files
 //------------------------------------------------------------------------------
 
-bool ReadProcFileFields(const std::string& path, const char* format, ...) {
+bool ReadProcFileFields(const std::string& path,
+                        absl::Nonnull<const char*> format, ...) {
   bool success = false;
   va_list value_list;
   va_start(value_list, format);
diff --git a/centipede/rusage_stats_test.cc b/centipede/rusage_stats_test.cc
index 0db36c3..95eb9a2 100644
--- a/centipede/rusage_stats_test.cc
+++ b/centipede/rusage_stats_test.cc
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/nullability.h"
 #include "absl/flags/flag.h"
 #include "absl/log/log.h"
 #include "absl/synchronization/barrier.h"
@@ -63,12 +64,12 @@
 // subsides too much.
 class CpuHog {
  public:
-  CpuHog(                                   //
-      absl::Duration idle_time,             //
-      absl::Duration hog_time,              //
-      int num_hogs,                         //
-      absl::Notification* hogging_started,  //
-      absl::Notification* hogging_stopped)
+  CpuHog(                                                  //
+      absl::Duration idle_time,                            //
+      absl::Duration hog_time,                             //
+      int num_hogs,                                        //
+      absl::Nonnull<absl::Notification*> hogging_started,  //
+      absl::Nonnull<absl::Notification*> hogging_stopped)
       : hog_barrier_{num_hogs}, hog_pool_{static_cast<size_t>(num_hogs)} {
     const auto hog_func = [=]() {
       const absl::Time start = absl::Now();
diff --git a/centipede/seed_corpus_maker.cc b/centipede/seed_corpus_maker.cc
index 91bca75..1cd7d52 100644
--- a/centipede/seed_corpus_maker.cc
+++ b/centipede/seed_corpus_maker.cc
@@ -16,6 +16,7 @@
 #include <filesystem>  // NOLINT
 #include <string>
 
+#include "absl/base/nullability.h"
 #include "absl/flags/flag.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
@@ -25,7 +26,7 @@
 #include "./centipede/seed_corpus_maker_lib.h"
 #include "./centipede/util.h"
 
-int main(int argc, char** argv) {
+int main(int argc, absl::Nonnull<char**> argv) {
   (void)centipede::config::InitRuntime(argc, argv);
 
   const std::string config = absl::GetFlag(FLAGS_config);
diff --git a/centipede/shared_memory_blob_sequence.cc b/centipede/shared_memory_blob_sequence.cc
index 2377f0b..98a8515 100644
--- a/centipede/shared_memory_blob_sequence.cc
+++ b/centipede/shared_memory_blob_sequence.cc
@@ -24,9 +24,11 @@
 #include <cstdint>
 #include <cstdio>
 
+#include "absl/base/nullability.h"
+
 namespace centipede {
 
-static void ErrorOnFailure(bool condition, const char *text) {
+static void ErrorOnFailure(bool condition, absl::Nonnull<const char *> text) {
   if (!condition) return;
   std::perror(text);
   abort();
diff --git a/centipede/shared_memory_blob_sequence.h b/centipede/shared_memory_blob_sequence.h
index 05a2c7e..82af0ab 100644
--- a/centipede/shared_memory_blob_sequence.h
+++ b/centipede/shared_memory_blob_sequence.h
@@ -20,6 +20,8 @@
 #include <cstdint>
 #include <type_traits>
 
+#include "absl/base/nullability.h"
+
 // This library must not depend on anything other than libc,
 // so that it does not introduce any dependencies to its users.
 // Any such dependencies may get coverage-instrumented, introducing noise
@@ -38,7 +40,7 @@
 // TODO(kcc): [impl] consider making it a class.
 struct Blob {
   using SizeAndTagT = size_t;
-  Blob(SizeAndTagT tag, SizeAndTagT size, const uint8_t *data)
+  Blob(SizeAndTagT tag, SizeAndTagT size, absl::Nullable<const uint8_t *> data)
       : tag(tag), size(size), data(data) {}
   Blob() = default;  // Construct an invalid Blob.
   bool IsValid() const { return tag != 0; }
@@ -167,7 +169,7 @@
   size_t NumBytesUsed() const;
 
   // Gets the file path that can be used to create new instances.
-  const char *path() const { return path_; }
+  absl::Nonnull<const char *> path() const { return path_; }
 
  private:
   // mmaps `size_` bytes from `fd_`, assigns to `data_`. Crashes if mmap failed.
diff --git a/centipede/testing/BUILD b/centipede/testing/BUILD
index 887ed03..2652040 100644
--- a/centipede/testing/BUILD
+++ b/centipede/testing/BUILD
@@ -65,6 +65,7 @@
         "notap",
     ],
     deps = [
+        "@com_google_absl//absl/base:nullability",
         "@com_google_fuzztest//centipede:centipede_runner_no_main",
         "@com_google_fuzztest//centipede:defs",
         "@com_google_fuzztest//centipede:mutation_input",
@@ -153,6 +154,7 @@
 cc_binary(
     name = "standalone_fuzz_target_with_main",
     srcs = ["standalone_fuzz_target_with_main.cc"],
+    deps = ["@com_google_absl//absl/base:nullability"],
 )
 
 ################################################################################
diff --git a/centipede/testing/seeded_fuzz_target.cc b/centipede/testing/seeded_fuzz_target.cc
index da3bf10..f42c5b9 100644
--- a/centipede/testing/seeded_fuzz_target.cc
+++ b/centipede/testing/seeded_fuzz_target.cc
@@ -17,6 +17,7 @@
 #include <functional>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "./centipede/defs.h"
 #include "./centipede/mutation_input.h"
 #include "./centipede/runner_interface.h"
@@ -45,7 +46,7 @@
   }
 };
 
-int main(int argc, char **argv) {
+int main(int argc, absl::Nonnull<char **> argv) {
   SeededRunnerCallbacks runner_callbacks;
   return centipede::RunnerMain(argc, argv, runner_callbacks);
 }
diff --git a/centipede/testing/standalone_fuzz_target_with_main.cc b/centipede/testing/standalone_fuzz_target_with_main.cc
index e9aee8c..870e4f8 100644
--- a/centipede/testing/standalone_fuzz_target_with_main.cc
+++ b/centipede/testing/standalone_fuzz_target_with_main.cc
@@ -21,9 +21,12 @@
 #include <cstdio>
 #include <cstdlib>
 
+#include "absl/base/nullability.h"
+
 // Separate no-inline function so that the compiler doesn't know
 // the size of `data`. Crashes when the input starts with 'fuz'.
-__attribute__((noinline)) static void FuzzMe(const uint8_t* data, size_t size) {
+__attribute__((noinline)) static void FuzzMe(absl::Nonnull<const uint8_t*> data,
+                                             size_t size) {
   if (size >= 3 && data[0] == 'f' && data[1] == 'u' && data[2] == 'z')
     __builtin_trap();
 }
diff --git a/centipede/util.cc b/centipede/util.cc
index 33b599e..6ce49c6 100644
--- a/centipede/util.cc
+++ b/centipede/util.cc
@@ -44,6 +44,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/const_init.h"
+#include "absl/base/nullability.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/log/check.h"
 #include "absl/strings/str_format.h"
@@ -234,9 +235,10 @@
 }
 
 // Reverse to a sequence of PackBytesForAppendFile() appended to each other.
-void UnpackBytesFromAppendFile(const ByteArray &packed_data,
-                               std::vector<ByteArray> *unpacked,
-                               std::vector<std::string> *hashes) {
+void UnpackBytesFromAppendFile(
+    const ByteArray &packed_data,
+    absl::Nonnull<std::vector<ByteArray> *> unpacked,
+    absl::Nullable<std::vector<std::string> *> hashes) {
   auto pos = packed_data.cbegin();
   while (true) {
     pos = std::search(pos, packed_data.end(), &kPackBegMagic[0],
@@ -293,7 +295,8 @@
   return feature_bytes_with_hash;
 }
 
-std::string UnpackFeaturesAndHash(const ByteSpan &blob, FeatureVec *features) {
+std::string UnpackFeaturesAndHash(const ByteSpan &blob,
+                                  absl::Nonnull<FeatureVec *> features) {
   size_t features_len_in_bytes = blob.size() - kHashLen;
   features->resize(features_len_in_bytes / sizeof(feature_t));
   memcpy(features->data(), blob.data(), features_len_in_bytes);
diff --git a/centipede/util.h b/centipede/util.h
index 359e5e1..54cbb28 100644
--- a/centipede/util.h
+++ b/centipede/util.h
@@ -22,6 +22,7 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/base/nullability.h"
 #include "absl/log/check.h"
 #include "absl/types/span.h"
 #include "./centipede/defs.h"
@@ -146,9 +147,10 @@
 // `packed_data` is multiple data packed by PackBytesForAppendFile()
 // and merged together.
 // `unpacked` or `hashes` can be nullptr.
-void UnpackBytesFromAppendFile(const ByteArray &packed_data,
-                               std::vector<ByteArray> *unpacked,
-                               std::vector<std::string> *hashes = nullptr);
+void UnpackBytesFromAppendFile(
+    const ByteArray &packed_data,
+    absl::Nonnull<std::vector<ByteArray> *> unpacked,
+    absl::Nullable<std::vector<std::string> *> hashes = nullptr);
 // Append the bytes from 'hash' to 'ba'.
 void AppendHashToArray(ByteArray &ba, std::string_view hash);
 // Reverse to AppendHashToArray.
@@ -164,7 +166,8 @@
 
 // Given a `blob` created by `PackFeaturesAndHash`, unpack the features into
 // `features` and return the hash.
-std::string UnpackFeaturesAndHash(const ByteSpan &blob, FeatureVec *features);
+std::string UnpackFeaturesAndHash(const ByteSpan &blob,
+                                  absl::Nonnull<FeatureVec *> features);
 
 // Parses `dictionary_text` representing an AFL/libFuzzer dictionary.
 // https://github.com/google/AFL/blob/master/dictionaries/README.dictionaries