No public description
PiperOrigin-RevId: 654772464
diff --git a/centipede/BUILD b/centipede/BUILD
index 1353510..cfa0875 100644
--- a/centipede/BUILD
+++ b/centipede/BUILD
@@ -515,6 +515,7 @@
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
],
)
@@ -597,6 +598,7 @@
"@com_google_fuzztest//common:defs",
"@com_google_fuzztest//common:logging",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
],
)
@@ -770,6 +772,7 @@
"@com_google_fuzztest//common:hash",
"@com_google_fuzztest//common:logging",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
],
)
@@ -815,6 +818,7 @@
"@com_google_fuzztest//common:hash",
"@com_google_fuzztest//common:logging",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
"@com_google_fuzztest//fuzztest:configuration",
],
)
@@ -843,6 +847,7 @@
"@com_google_fuzztest//common:defs",
"@com_google_fuzztest//common:logging",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
],
)
@@ -874,6 +879,7 @@
"@com_google_fuzztest//common:hash",
"@com_google_fuzztest//common:logging",
"@com_google_fuzztest//common:remote_file",
+ "@com_google_fuzztest//common:status_macros",
],
)
diff --git a/centipede/analyze_corpora.cc b/centipede/analyze_corpora.cc
index 6297d84..e4a8f6c 100644
--- a/centipede/analyze_corpora.cc
+++ b/centipede/analyze_corpora.cc
@@ -48,9 +48,11 @@
WorkDir workdir(std::string(workdir_path), std::string(binary_name),
std::string(binary_hash), /*my_shard_index=*/0);
std::vector<std::string> corpus_paths;
- RemoteGlobMatch(workdir.CorpusFiles().AllShardsGlob(), corpus_paths);
+ CHECK_OK(
+ RemoteGlobMatch(workdir.CorpusFiles().AllShardsGlob(), corpus_paths));
std::vector<std::string> features_paths;
- RemoteGlobMatch(workdir.FeaturesFiles().AllShardsGlob(), features_paths);
+ CHECK_OK(
+ RemoteGlobMatch(workdir.FeaturesFiles().AllShardsGlob(), features_paths));
CHECK_EQ(corpus_paths.size(), features_paths.size());
std::vector<CorpusRecord> corpus;
@@ -193,7 +195,8 @@
std::ostringstream symbol_table_stream;
coverage_symbol_table.WriteToLLVMSymbolizer(symbol_table_stream);
- RemoteFileSetContents(coverage_report_path, symbol_table_stream.str());
+ CHECK_OK(
+ RemoteFileSetContents(coverage_report_path, symbol_table_stream.str()));
}
AnalyzeCorporaResults AnalyzeCorpora(std::string_view binary_name,
diff --git a/centipede/analyze_corpora_test.cc b/centipede/analyze_corpora_test.cc
index 055b053..f72effa 100644
--- a/centipede/analyze_corpora_test.cc
+++ b/centipede/analyze_corpora_test.cc
@@ -102,7 +102,7 @@
std::filesystem::path{test_tmpdir} / "covered_symbol_table";
DumpCoverageReport(coverage_results, coverage_report_path);
std::string symbol_table_contents;
- RemoteFileGetContents(coverage_report_path, symbol_table_contents);
+ ASSERT_OK(RemoteFileGetContents(coverage_report_path, symbol_table_contents));
std::istringstream symbol_table_stream(symbol_table_contents);
SymbolTable symbols;
diff --git a/centipede/binary_info.cc b/centipede/binary_info.cc
index 073e508..e822dca 100644
--- a/centipede/binary_info.cc
+++ b/centipede/binary_info.cc
@@ -123,15 +123,16 @@
void BinaryInfo::Read(std::string_view dir) {
std::string symbol_table_contents;
// TODO(b/295978603): move calculation of paths into WorkDir class.
- RemoteFileGetContents(
+ CHECK_OK(RemoteFileGetContents(
(std::filesystem::path(dir) / kSymbolTableFileName).c_str(),
- symbol_table_contents);
+ symbol_table_contents));
std::istringstream symbol_table_stream(symbol_table_contents);
symbols.ReadFromLLVMSymbolizer(symbol_table_stream);
std::string pc_table_contents;
- RemoteFileGetContents((std::filesystem::path(dir) / kPCTableFileName).c_str(),
- pc_table_contents);
+ CHECK_OK(RemoteFileGetContents(
+ (std::filesystem::path(dir) / kPCTableFileName).c_str(),
+ pc_table_contents));
std::istringstream pc_table_stream(pc_table_contents);
pc_table = ReadPcTable(pc_table_stream);
}
@@ -140,14 +141,15 @@
std::ostringstream symbol_table_stream;
symbols.WriteToLLVMSymbolizer(symbol_table_stream);
// TODO(b/295978603): move calculation of paths into WorkDir class.
- RemoteFileSetContents(
+ CHECK_OK(RemoteFileSetContents(
(std::filesystem::path(dir) / kSymbolTableFileName).c_str(),
- symbol_table_stream.str());
+ symbol_table_stream.str()));
std::ostringstream pc_table_stream;
WritePcTable(pc_table, pc_table_stream);
- RemoteFileSetContents((std::filesystem::path(dir) / kPCTableFileName).c_str(),
- pc_table_stream.str());
+ CHECK_OK(RemoteFileSetContents(
+ (std::filesystem::path(dir) / kPCTableFileName).c_str(),
+ pc_table_stream.str()));
}
} // namespace centipede
diff --git a/centipede/blob_file_converter.cc b/centipede/blob_file_converter.cc
index 93af3c7..226e741 100644
--- a/centipede/blob_file_converter.cc
+++ b/centipede/blob_file_converter.cc
@@ -99,7 +99,7 @@
// Verify and prepare source and destination.
CHECK(RemotePathExists(in)) << VV(in);
- RemoteMkdir(std::filesystem::path{out}.parent_path().c_str());
+ CHECK_OK(RemoteMkdir(std::filesystem::path{out}.parent_path().c_str()));
// Open blob file reader and writer.
diff --git a/centipede/centipede.cc b/centipede/centipede.cc
index 1f97cdc..ac408d2 100644
--- a/centipede/centipede.cc
+++ b/centipede/centipede.cc
@@ -96,6 +96,7 @@
#include "./common/hash.h"
#include "./common/logging.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
namespace centipede {
@@ -135,8 +136,8 @@
void Centipede::CorpusToFiles(const Environment &env, std::string_view dir) {
std::vector<std::string> sharded_corpus_files;
- RemoteGlobMatch(WorkDir{env}.CorpusFiles().AllShardsGlob(),
- sharded_corpus_files);
+ CHECK_OK(RemoteGlobMatch(WorkDir{env}.CorpusFiles().AllShardsGlob(),
+ sharded_corpus_files));
ExportCorpus(sharded_corpus_files, dir);
}
@@ -147,7 +148,9 @@
std::vector<std::vector<std::string>> sharded_paths(env.total_shards);
std::vector<std::string> paths;
size_t total_paths = 0;
- for (const std::string &path : RemoteListFiles(dir, /*recursively=*/true)) {
+ const std::vector<std::string> listed_paths =
+ ValueOrDie(RemoteListFiles(dir, /*recursively=*/true));
+ for (const std::string &path : listed_paths) {
size_t filename_hash = std::hash<std::string>{}(path);
sharded_paths[filename_hash % env.total_shards].push_back(path);
++total_paths;
@@ -177,7 +180,7 @@
ByteArray shard_data;
for (const auto &path : sharded_paths[shard]) {
std::string input;
- RemoteFileGetContents(path, input);
+ CHECK_OK(RemoteFileGetContents(path, input));
if (input.empty() || existing_hashes.contains(Hash(input))) {
++inputs_ignored;
continue;
@@ -533,7 +536,7 @@
auto report_path = wd_.SourceBasedCoverageReportPath(filename_annotation);
LOG(INFO) << "Generate source based coverage report [" << description << "]; "
<< VV(report_path);
- RemoteMkdir(report_path);
+ CHECK_OK(RemoteMkdir(report_path));
std::vector<std::string> raw_profiles = wd_.EnumerateRawCoverageProfiles();
@@ -574,15 +577,16 @@
class ReportDumper : public RUsageProfiler::ReportSink {
public:
explicit ReportDumper(std::string_view path)
- : file_{RemoteFileOpen(path, "w")} {
+ : file_{*RemoteFileOpen(path, "w")} {
CHECK(file_ != nullptr) << VV(path);
- RemoteFileSetWriteBufferSize(file_, 10UL * 1024 * 1024);
+ CHECK_OK(RemoteFileSetWriteBufferSize(file_, 10UL * 1024 * 1024));
}
- ~ReportDumper() override { RemoteFileClose(file_); }
+ ~ReportDumper() override { CHECK_OK(RemoteFileClose(file_)); }
ReportDumper &operator<<(std::string_view fragment) override {
- RemoteFileAppend(file_, ByteArray{fragment.cbegin(), fragment.cend()});
+ CHECK_OK(RemoteFileAppend(file_,
+ ByteArray{fragment.cbegin(), fragment.cend()}));
return *this;
}
@@ -870,7 +874,7 @@
if (!user_callbacks_.Execute(binary, {one_input}, one_input_batch_result)) {
auto hash = Hash(one_input);
auto crash_dir = wd_.CrashReproducerDirPath();
- RemoteMkdir(crash_dir);
+ CHECK_OK(RemoteMkdir(crash_dir));
std::string file_path = std::filesystem::path(crash_dir).append(hash);
LOG(INFO) << log_prefix << "Detected crash-reproducing input:"
<< "\nInput index : " << input_idx << "\nInput bytes : "
@@ -879,7 +883,7 @@
<< "\nFailure : "
<< one_input_batch_result.failure_description()
<< "\nSaving input to: " << file_path;
- RemoteFileSetContents(file_path, one_input);
+ CHECK_OK(RemoteFileSetContents(file_path, one_input));
return;
}
}
@@ -898,18 +902,18 @@
const auto &suspect_input = input_vec[suspect_input_idx];
auto suspect_hash = Hash(suspect_input);
auto crash_dir = wd_.CrashReproducerDirPath();
- RemoteMkdir(crash_dir);
+ CHECK_OK(RemoteMkdir(crash_dir));
std::string save_dir = std::filesystem::path(crash_dir)
.append("crashing_batch-")
.concat(suspect_hash);
- RemoteMkdir(save_dir);
+ CHECK_OK(RemoteMkdir(save_dir));
LOG(INFO) << log_prefix << "Saving used inputs from batch to: " << save_dir;
for (int i = 0; i <= suspect_input_idx; ++i) {
const auto &one_input = input_vec[i];
auto hash = Hash(one_input);
std::string file_path = std::filesystem::path(save_dir).append(
absl::StrFormat("input-%010d-%s", i, hash));
- RemoteFileSetContents(file_path, one_input);
+ CHECK_OK(RemoteFileSetContents(file_path, one_input));
}
}
diff --git a/centipede/centipede_interface.cc b/centipede/centipede_interface.cc
index 73dcb09..1d970dd 100644
--- a/centipede/centipede_interface.cc
+++ b/centipede/centipede_interface.cc
@@ -66,6 +66,7 @@
#include "./common/hash.h"
#include "./common/logging.h" // IWYU pragma: keep
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
#include "./fuzztest/internal/configuration.h"
namespace centipede {
@@ -178,7 +179,7 @@
}
if (env.save_binary_info) {
const std::string binary_info_dir = WorkDir{env}.BinaryInfoDirPath();
- RemoteMkdir(binary_info_dir);
+ CHECK_OK(RemoteMkdir(binary_info_dir));
LOG(INFO) << "Serializing binary info to: " << binary_info_dir;
binary_info.Write(binary_info_dir);
}
@@ -329,11 +330,11 @@
for (const std::string &crashing_input_file : crashing_input_files) {
ByteArray crashing_input;
- RemoteFileGetContents(crashing_input_file, crashing_input);
+ CHECK_OK(RemoteFileGetContents(crashing_input_file, crashing_input));
if (scoped_callbacks.callbacks()->Execute(env.binary, {crashing_input},
batch_result)) {
// The crash is not reproducible.
- RemotePathDelete(crashing_input_file, /*recursively=*/false);
+ CHECK_OK(RemotePathDelete(crashing_input_file, /*recursively=*/false));
} else {
++num_remaining_crashes;
}
@@ -435,10 +436,11 @@
// This could be a workdir from a failed run that used a different version
// of the binary. We delete it so that we don't have to deal with the
// assumptions under which it is safe to reuse an old workdir.
- RemotePathDelete(env.workdir, /*recursively=*/true);
+ CHECK_OK(RemotePathDelete(env.workdir, /*recursively=*/true));
}
const WorkDir workdir{env};
- RemoteMkdir(workdir.CoverageDirPath()); // Implicitly creates the workdir.
+ CHECK_OK(RemoteMkdir(
+ workdir.CoverageDirPath())); // Implicitly creates the workdir
// Seed the fuzzing session with the latest coverage corpus from the
// previous fuzzing session.
@@ -465,11 +467,11 @@
Fuzz(env, binary_info, pcs_file_path, callbacks_factory);
if (!stats_root_path.empty()) {
const auto stats_dir = stats_root_path / fuzztest_config.fuzz_tests[i];
- RemoteMkdir(stats_dir.c_str());
- RemotePathRename(
+ CHECK_OK(RemoteMkdir(stats_dir.c_str()));
+ CHECK_OK(RemotePathRename(
workdir.FuzzingStatsPath(),
(stats_dir / absl::StrCat("fuzzing_stats_", execution_stamp))
- .c_str());
+ .c_str()));
}
// Distill and store the coverage corpus.
@@ -477,23 +479,25 @@
if (RemotePathExists(coverage_dir.c_str())) {
// In the future, we will store k latest coverage corpora for some k, but
// for now we only keep the latest one.
- RemotePathDelete(coverage_dir.c_str(), /*recursively=*/true);
+ CHECK_OK(RemotePathDelete(coverage_dir.c_str(), /*recursively=*/true));
}
- RemoteMkdir(coverage_dir.c_str());
+ CHECK_OK(RemoteMkdir(coverage_dir.c_str()));
std::vector<std::string> distilled_corpus_files;
- RemoteGlobMatch(workdir.DistilledCorpusFiles().AllShardsGlob(),
- distilled_corpus_files);
+ CHECK_OK(RemoteGlobMatch(workdir.DistilledCorpusFiles().AllShardsGlob(),
+ distilled_corpus_files));
for (const std::string &corpus_file : distilled_corpus_files) {
const std::string file_name =
std::filesystem::path(corpus_file).filename();
- RemotePathRename(corpus_file, (coverage_dir / file_name).c_str());
+ CHECK_OK(
+ RemotePathRename(corpus_file, (coverage_dir / file_name).c_str()));
}
const std::filesystem::path crashing_dir = fuzztest_db_path / "crashing";
const std::vector<std::string> crashing_input_files =
// The corpus database layout assumes the crash input files are located
// directly in the crashing subdirectory, so we don't list recursively.
- RemoteListFiles(crashing_dir.c_str(), /*recursively=*/false);
+ ValueOrDie(
+ RemoteListFiles(crashing_dir.c_str(), /*recursively=*/false));
const int num_remaining_crashes =
PruneNonreproducibleAndCountRemainingCrashes(env, crashing_input_files,
callbacks_factory);
@@ -505,18 +509,19 @@
// The crash reproducer directory may contain subdirectories with
// input files that don't individually cause a crash. We ignore those
// for now and don't list the files recursively.
- RemoteListFiles(workdir.CrashReproducerDirPath(),
- /*recursively=*/false);
+ *RemoteListFiles(workdir.CrashReproducerDirPath(),
+ /*recursively=*/false);
if (!new_crashing_input_files.empty()) {
const std::string crashing_input_file_name =
std::filesystem::path(new_crashing_input_files[0]).filename();
- RemoteMkdir(crashing_dir.c_str());
- RemotePathRename(new_crashing_input_files[0],
- (crashing_dir / crashing_input_file_name).c_str());
+ CHECK_OK(RemoteMkdir(crashing_dir.c_str()));
+ CHECK_OK(RemotePathRename(
+ new_crashing_input_files[0],
+ (crashing_dir / crashing_input_file_name).c_str()));
}
}
}
- RemotePathDelete(base_workdir_path.c_str(), /*recursively=*/true);
+ CHECK_OK(RemotePathDelete(base_workdir_path.c_str(), /*recursively=*/true));
return EXIT_SUCCESS;
}
@@ -589,7 +594,7 @@
// Create the remote coverage dirs once, before creating any threads.
const auto coverage_dir = WorkDir{env}.CoverageDirPath();
- RemoteMkdir(coverage_dir);
+ CHECK_OK(RemoteMkdir(coverage_dir));
LOG(INFO) << "Coverage dir: " << coverage_dir
<< "; temporary dir: " << tmpdir;
diff --git a/centipede/config_file.cc b/centipede/config_file.cc
index c03df11..2c1e29c 100644
--- a/centipede/config_file.cc
+++ b/centipede/config_file.cc
@@ -162,15 +162,15 @@
if (!path.empty() && !std::filesystem::exists(path)) { // assume remote
// Read the remote file.
std::string contents;
- RemoteFileGetContents(path.c_str(), contents);
+ CHECK_OK(RemoteFileGetContents(path.c_str(), contents));
// Save a temporary local copy.
const std::filesystem::path tmp_dir = TemporaryLocalDirPath();
const std::filesystem::path local_path = tmp_dir / path.filename();
LOG(INFO) << "Localizing remote config: " << VV(path) << VV(local_path);
// NOTE: Ignore "Remote" in the API names here: the paths are always local.
- RemoteMkdir(tmp_dir.c_str());
- RemoteFileSetContents(local_path.c_str(), contents);
+ CHECK_OK(RemoteMkdir(tmp_dir.c_str()));
+ CHECK_OK(RemoteFileSetContents(local_path.c_str(), contents));
// Augment the argv to point at the local copy and ensure it is cleaned up.
replacements.emplace_back(path.c_str(), local_path.c_str());
@@ -244,7 +244,7 @@
} else {
file_contents = flags_str;
}
- RemoteFileSetContents(path.c_str(), file_contents);
+ CHECK_OK(RemoteFileSetContents(path.c_str(), file_contents));
}
return path;
diff --git a/centipede/corpus.cc b/centipede/corpus.cc
index ba6cf44..a6c956b 100644
--- a/centipede/corpus.cc
+++ b/centipede/corpus.cc
@@ -37,6 +37,7 @@
#include "./common/defs.h"
#include "./common/logging.h" // IWYU pragma: keep
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
namespace centipede {
@@ -136,9 +137,9 @@
void Corpus::DumpStatsToFile(const FeatureSet &fs, std::string_view filepath,
std::string_view description) {
- auto *file = RemoteFileOpen(filepath, "w");
+ auto *file = ValueOrDie(RemoteFileOpen(filepath, "w"));
CHECK(file != nullptr) << "Failed to open file: " << filepath;
- RemoteFileSetWriteBufferSize(file, 100UL * 1024 * 1024);
+ CHECK_OK(RemoteFileSetWriteBufferSize(file, 100UL * 1024 * 1024));
static constexpr std::string_view kHeaderStub = R"(# $0
{
"num_inputs": $1,
@@ -151,7 +152,7 @@
)";
const std::string header_str =
absl::Substitute(kHeaderStub, description, records_.size());
- RemoteFileAppend(file, header_str);
+ CHECK_OK(RemoteFileAppend(file, header_str));
std::string before_record;
for (const auto &record : records_) {
std::vector<size_t> frequencies;
@@ -162,11 +163,11 @@
const std::string frequencies_str = absl::StrJoin(frequencies, ", ");
const std::string record_str = absl::Substitute(
kRecordStub, before_record, record.data.size(), frequencies_str);
- RemoteFileAppend(file, record_str);
+ CHECK_OK(RemoteFileAppend(file, record_str));
before_record = ",";
}
- RemoteFileAppend(file, std::string{kFooter});
- RemoteFileClose(file);
+ CHECK_OK(RemoteFileAppend(file, std::string{kFooter}));
+ CHECK_OK(RemoteFileClose(file));
}
std::string Corpus::MemoryUsageString() const {
diff --git a/centipede/coverage.cc b/centipede/coverage.cc
index 1f91e56..66aa328 100644
--- a/centipede/coverage.cc
+++ b/centipede/coverage.cc
@@ -33,6 +33,7 @@
#include "./centipede/pc_info.h"
#include "./centipede/symbol_table.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
namespace centipede {
@@ -90,47 +91,47 @@
void Coverage::DumpReportToFile(const SymbolTable &symbols,
std::string_view filepath,
std::string_view description) {
- auto *file = RemoteFileOpen(filepath, "w");
+ auto *file = ValueOrDie(RemoteFileOpen(filepath, "w"));
CHECK(file != nullptr) << "Failed to open file: " << filepath;
- RemoteFileSetWriteBufferSize(file, 100UL * 1024 * 1024);
+ CHECK_OK(RemoteFileSetWriteBufferSize(file, 100UL * 1024 * 1024));
if (!description.empty()) {
- RemoteFileAppend(file, "# ");
- RemoteFileAppend(file, std::string{description});
- RemoteFileAppend(file, ":\n\n");
+ CHECK_OK(RemoteFileAppend(file, "# "));
+ CHECK_OK(RemoteFileAppend(file, std::string{description}));
+ CHECK_OK(RemoteFileAppend(file, ":\n\n"));
}
// Print symbolized function names for all covered functions.
for (auto pc_index : fully_covered_funcs) {
- RemoteFileAppend(file, "FULL: ");
- RemoteFileAppend(file, symbols.full_description(pc_index));
- RemoteFileAppend(file, "\n");
+ CHECK_OK(RemoteFileAppend(file, "FULL: "));
+ CHECK_OK(RemoteFileAppend(file, symbols.full_description(pc_index)));
+ CHECK_OK(RemoteFileAppend(file, "\n"));
}
- RemoteFileFlush(file);
+ CHECK_OK(RemoteFileFlush(file));
// Same for uncovered functions.
for (auto pc_index : uncovered_funcs) {
- RemoteFileAppend(file, "NONE: ");
- RemoteFileAppend(file, symbols.full_description(pc_index));
- RemoteFileAppend(file, "\n");
+ CHECK_OK(RemoteFileAppend(file, "NONE: "));
+ CHECK_OK(RemoteFileAppend(file, symbols.full_description(pc_index)));
+ CHECK_OK(RemoteFileAppend(file, "\n"));
}
- RemoteFileFlush(file);
+ CHECK_OK(RemoteFileFlush(file));
// For every partially covered function, first print its name,
// then print its covered edges, then uncovered edges.
for (auto &pcf : partially_covered_funcs) {
- RemoteFileAppend(file, "PARTIAL: ");
- RemoteFileAppend(file, symbols.full_description(pcf.covered[0]));
- RemoteFileAppend(file, "\n");
+ CHECK_OK(RemoteFileAppend(file, "PARTIAL: "));
+ CHECK_OK(RemoteFileAppend(file, symbols.full_description(pcf.covered[0])));
+ CHECK_OK(RemoteFileAppend(file, "\n"));
for (auto pc_index : pcf.covered) {
- RemoteFileAppend(file, " + ");
- RemoteFileAppend(file, symbols.full_description(pc_index));
- RemoteFileAppend(file, "\n");
+ CHECK_OK(RemoteFileAppend(file, " + "));
+ CHECK_OK(RemoteFileAppend(file, symbols.full_description(pc_index)));
+ CHECK_OK(RemoteFileAppend(file, "\n"));
}
for (auto pc_index : pcf.uncovered) {
- RemoteFileAppend(file, " - ");
- RemoteFileAppend(file, symbols.full_description(pc_index));
- RemoteFileAppend(file, "\n");
+ CHECK_OK(RemoteFileAppend(file, " - "));
+ CHECK_OK(RemoteFileAppend(file, symbols.full_description(pc_index)));
+ CHECK_OK(RemoteFileAppend(file, "\n"));
}
}
- RemoteFileFlush(file);
- RemoteFileClose(file);
+ CHECK_OK(RemoteFileFlush(file));
+ CHECK_OK(RemoteFileClose(file));
}
std::string CoverageLogger::ObserveAndDescribeIfNew(PCIndex pc_index) {
diff --git a/centipede/distill.cc b/centipede/distill.cc
index 5f79705..84e8c13 100644
--- a/centipede/distill.cc
+++ b/centipede/distill.cc
@@ -52,6 +52,7 @@
#include "./common/hash.h"
#include "./common/logging.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
namespace centipede {
@@ -116,8 +117,10 @@
perf::MemSize EstimateRamFootprint(size_t shard_idx) const {
const auto corpus_path = workdir_.CorpusFiles().ShardPath(shard_idx);
const auto features_path = workdir_.FeaturesFiles().ShardPath(shard_idx);
- const perf::MemSize corpus_file_size = RemoteFileGetSize(corpus_path);
- const perf::MemSize features_file_size = RemoteFileGetSize(features_path);
+ const perf::MemSize corpus_file_size =
+ ValueOrDie(RemoteFileGetSize(corpus_path));
+ const perf::MemSize features_file_size =
+ ValueOrDie(RemoteFileGetSize(features_path));
// Conservative compression factors for the two file types. These have been
// observed empirically for the Riegeli blob format. The legacy format is
// approximately 1:1, but use the stricter Riegeli numbers, as the legacy
diff --git a/centipede/environment.cc b/centipede/environment.cc
index f1fba17..9b1e309 100644
--- a/centipede/environment.cc
+++ b/centipede/environment.cc
@@ -33,6 +33,7 @@
#include "./common/defs.h"
#include "./common/logging.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
namespace centipede {
@@ -192,10 +193,10 @@
const std::string_view knobs_file_path = knobs_file;
if (knobs_file_path.empty()) return;
ByteArray knob_bytes;
- auto *f = RemoteFileOpen(knobs_file, "r");
+ auto *f = ValueOrDie(RemoteFileOpen(knobs_file, "r"));
CHECK(f) << "Failed to open remote file " << knobs_file;
- RemoteFileRead(f, knob_bytes);
- RemoteFileClose(f);
+ CHECK_OK(RemoteFileRead(f, knob_bytes));
+ CHECK_OK(RemoteFileClose(f));
VLOG(1) << "Knobs: " << knob_bytes.size() << " knobs read from "
<< knobs_file;
knobs.Set(knob_bytes);
diff --git a/centipede/seed_corpus_maker_lib.cc b/centipede/seed_corpus_maker_lib.cc
index b94f516..c075465 100644
--- a/centipede/seed_corpus_maker_lib.cc
+++ b/centipede/seed_corpus_maker_lib.cc
@@ -92,7 +92,7 @@
LOG(INFO) << "Config spec points at an existing file; trying to parse "
"textproto config from it: "
<< VV(config_spec);
- RemoteFileGetContents(config_spec, config_str);
+ CHECK_OK(RemoteFileGetContents(config_spec, config_str));
LOG(INFO) << "Raw config read from file:\n" << config_str;
base_dir = std::filesystem::path{config_spec}.parent_path();
} else {
@@ -161,7 +161,7 @@
// `source.num_recent_dirs()` most recent ones.
std::vector<std::string> src_dirs;
- RemoteGlobMatch(source.dir_glob(), src_dirs);
+ CHECK_OK(RemoteGlobMatch(source.dir_glob(), src_dirs));
LOG(INFO) << "Found " << src_dirs.size() << " corpus dir(s) matching "
<< source.dir_glob();
// Sort in the ascending lexicographical order. We expect that dir names
@@ -179,7 +179,7 @@
const std::string shards_glob = fs::path{dir} / source.shard_rel_glob();
// NOTE: `RemoteGlobMatch` appends to the output list.
const auto prev_num_shards = corpus_shard_fnames.size();
- RemoteGlobMatch(shards_glob, corpus_shard_fnames);
+ CHECK_OK(RemoteGlobMatch(shards_glob, corpus_shard_fnames));
LOG(INFO) << "Found " << (corpus_shard_fnames.size() - prev_num_shards)
<< " shard(s) matching " << shards_glob;
}
@@ -422,7 +422,9 @@
for (const auto& fname : {corpus_fname, features_fname}) {
if (!fname.empty()) {
const auto dir = fs::path{fname}.parent_path().string();
- if (!RemotePathExists(dir)) RemoteMkdir(dir);
+ if (!RemotePathExists(dir)) {
+ CHECK_OK(RemoteMkdir(dir));
+ }
}
}
@@ -502,7 +504,7 @@
std::string_view override_out_dir) {
// Pre-create the destination dir early to catch possible misspellings etc.
if (!RemotePathExists(config.destination().dir_path())) {
- RemoteMkdir(config.destination().dir_path());
+ CHECK_OK(RemoteMkdir(config.destination().dir_path()));
}
// Dump the config to the debug info dir in the destination.
@@ -513,9 +515,9 @@
/*my_shard_index=*/0,
};
const std::filesystem::path debug_info_dir = workdir.DebugInfoDirPath();
- RemoteMkdir(debug_info_dir.c_str());
- RemoteFileSetContents((debug_info_dir / "seeding.cfg").c_str(),
- absl::StrCat(config));
+ CHECK_OK(RemoteMkdir(debug_info_dir.c_str()));
+ CHECK_OK(RemoteFileSetContents((debug_info_dir / "seeding.cfg").c_str(),
+ absl::StrCat(config)));
InputAndFeaturesVec elements;
diff --git a/centipede/stats.cc b/centipede/stats.cc
index 2f96801..dbffda2 100644
--- a/centipede/stats.cc
+++ b/centipede/stats.cc
@@ -172,7 +172,7 @@
StatsCsvFileAppender::~StatsCsvFileAppender() {
for (const auto &[group_name, file] : files_) {
- RemoteFileClose(file.file);
+ CHECK_OK(RemoteFileClose(file.file));
}
}
@@ -206,20 +206,20 @@
bool append = false;
if (RemotePathExists(filename)) {
std::string contents;
- RemoteFileGetContents(filename, contents);
+ CHECK_OK(RemoteFileGetContents(filename, contents));
// NOTE: `csv_header_` ends with '\n', so the match is exact.
if (absl::StartsWith(contents, csv_header_)) {
append = true;
} else {
append = false;
- RemoteFileSetContents(GetBackupFilename(filename), contents);
+ CHECK_OK(RemoteFileSetContents(GetBackupFilename(filename), contents));
}
}
- file.file = RemoteFileOpen(filename, append ? "a" : "w");
+ file.file = *RemoteFileOpen(filename, append ? "a" : "w");
CHECK(file.file != nullptr) << VV(filename);
if (!append) {
- RemoteFileAppend(file.file, csv_header_);
- RemoteFileFlush(file.file);
+ CHECK_OK(RemoteFileAppend(file.file, csv_header_));
+ CHECK_OK(RemoteFileFlush(file.file));
}
}
curr_file_ = &file;
@@ -260,8 +260,8 @@
void StatsCsvFileAppender::DoneFieldSamplesBatch() {
for (auto &&[group_name, file] : files_) {
- RemoteFileAppend(file.file, absl::StrCat(file.buffer, "\n"));
- RemoteFileFlush(file.file);
+ CHECK_OK(RemoteFileAppend(file.file, absl::StrCat(file.buffer, "\n")));
+ CHECK_OK(RemoteFileFlush(file.file));
file.buffer.clear();
}
}
diff --git a/centipede/util.cc b/centipede/util.cc
index fca9831..09ecb6c 100644
--- a/centipede/util.cc
+++ b/centipede/util.cc
@@ -140,13 +140,14 @@
void WriteToRemoteHashedFileInDir(std::string_view dir_path, ByteSpan data) {
if (dir_path.empty()) return;
std::string file_path = std::filesystem::path(dir_path).append(Hash(data));
- RemoteFileSetContents(file_path, std::string(data.begin(), data.end()));
+ CHECK_OK(
+ RemoteFileSetContents(file_path, std::string(data.begin(), data.end())));
}
std::string HashOfFileContents(std::string_view file_path) {
if (file_path.empty()) return "";
std::string file_contents;
- RemoteFileGetContents(file_path, file_contents);
+ CHECK_OK(RemoteFileGetContents(file_path, file_contents));
return Hash(file_contents);
}
diff --git a/common/BUILD b/common/BUILD
index 34c69f4..136a811 100644
--- a/common/BUILD
+++ b/common/BUILD
@@ -49,6 +49,7 @@
":hash",
":logging",
":remote_file",
+ ":status_macros",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
@@ -107,8 +108,12 @@
deps = [
":defs",
":logging",
+ ":status_macros",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/log:check",
+ "@com_google_absl//absl/status",
+ "@com_google_absl//absl/status:statusor",
+ "@com_google_absl//absl/strings",
] + select({
"//conditions:default": [":remote_file_oss"],
}) +
@@ -135,9 +140,13 @@
deps = [
":defs",
":logging",
+ ":status_macros",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
+ "@com_google_absl//absl/status",
+ "@com_google_absl//absl/status:statusor",
+ "@com_google_absl//absl/strings",
] + select({
"@com_google_fuzztest//fuzztest:disable_riegeli": [],
"//conditions:default": [
@@ -150,6 +159,16 @@
)
cc_library(
+ name = "status_macros",
+ hdrs = ["status_macros.h"],
+ deps = [
+ "@com_google_absl//absl/base:core_headers",
+ "@com_google_absl//absl/log",
+ "@com_google_absl//absl/types:source_location",
+ ],
+)
+
+cc_library(
name = "test_util",
testonly = True,
srcs = ["test_util.cc"],
diff --git a/common/blob_file.cc b/common/blob_file.cc
index 9fafe8e..5011051 100644
--- a/common/blob_file.cc
+++ b/common/blob_file.cc
@@ -37,6 +37,7 @@
#include "./common/hash.h"
#include "./common/logging.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
#ifndef CENTIPEDE_DISABLE_RIEGELI
#include "riegeli/base/object.h"
#include "riegeli/base/types.h"
@@ -76,14 +77,15 @@
absl::Status Open(std::string_view path) override {
if (closed_) return absl::FailedPreconditionError("already closed");
if (file_) return absl::FailedPreconditionError("already open");
- file_ = RemoteFileOpen(path, "r");
+ ASSIGN_OR_RETURN_IF_NOT_OK(file_, RemoteFileOpen(path, "r"));
if (file_ == nullptr) return absl::UnknownError("can't open file");
// Read the entire file at once.
// It may be useful to read the file in chunks, but if we are going
// to migrate to something else, it's not important here.
ByteArray raw_bytes;
- RemoteFileRead(file_, raw_bytes);
- RemoteFileClose(file_); // close the file here, we won't need it.
+ RETURN_IF_NOT_OK(RemoteFileRead(file_, raw_bytes));
+ RETURN_IF_NOT_OK(
+ RemoteFileClose(file_)); // close the file here, we won't need it.
UnpackBytesFromAppendFile(raw_bytes, &unpacked_blobs_);
return absl::OkStatus();
}
@@ -130,9 +132,9 @@
CHECK(mode == "w" || mode == "a") << VV(mode);
if (closed_) return absl::FailedPreconditionError("already closed");
if (file_) return absl::FailedPreconditionError("already open");
- file_ = RemoteFileOpen(path, mode.data());
+ ASSIGN_OR_RETURN_IF_NOT_OK(file_, RemoteFileOpen(path, mode.data()));
if (file_ == nullptr) return absl::UnknownError("can't open file");
- RemoteFileSetWriteBufferSize(file_, kMaxBufferedBytes);
+ RETURN_IF_NOT_OK(RemoteFileSetWriteBufferSize(file_, kMaxBufferedBytes));
return absl::OkStatus();
}
@@ -140,8 +142,8 @@
if (closed_) return absl::FailedPreconditionError("already closed");
if (!file_) return absl::FailedPreconditionError("was not open");
ByteArray packed = PackBytesForAppendFile(blob);
- RemoteFileAppend(file_, packed);
- RemoteFileFlush(file_);
+ RETURN_IF_NOT_OK(RemoteFileAppend(file_, packed));
+ RETURN_IF_NOT_OK(RemoteFileFlush(file_));
return absl::OkStatus();
}
@@ -149,7 +151,7 @@
if (closed_) return absl::FailedPreconditionError("already closed");
if (!file_) return absl::FailedPreconditionError("was not open");
closed_ = true;
- RemoteFileClose(file_);
+ RETURN_IF_NOT_OK(RemoteFileClose(file_));
return absl::OkStatus();
}
@@ -174,7 +176,9 @@
if (absl::Status s = Close(); !s.ok()) return s;
#ifndef CENTIPEDE_DISABLE_RIEGELI
- riegeli_reader_.Reset(CreateRiegeliFileReader(path));
+ ASSIGN_OR_RETURN_IF_NOT_OK(std::unique_ptr<riegeli::Reader> new_reader,
+ CreateRiegeliFileReader(path));
+ riegeli_reader_.Reset(std::move(new_reader));
if (riegeli_reader_.CheckFileFormat()) [[likely]] {
// File could be opened and is in the Riegeli format.
return absl::OkStatus();
@@ -277,8 +281,10 @@
if (absl::Status s = Close(); !s.ok()) return s;
const auto kWriterOpts =
riegeli::RecordWriterBase::Options{}.set_chunk_size(kMaxBufferedBytes);
- writer_.Reset(CreateRiegeliFileWriter(path, mode == "a"), kWriterOpts);
- if (!writer_.ok()) return writer_.status();
+ ASSIGN_OR_RETURN_IF_NOT_OK(std::unique_ptr<riegeli::Writer> new_writer,
+ CreateRiegeliFileWriter(path, mode == "a"));
+ writer_.Reset(std::move(new_writer), kWriterOpts);
+ RETURN_IF_NOT_OK(writer_.status());
path_ = path;
opened_at_ = absl::Now();
flushed_at_ = absl::Now();
diff --git a/common/remote_file.cc b/common/remote_file.cc
index eb761e6..633cd0a 100644
--- a/common/remote_file.cc
+++ b/common/remote_file.cc
@@ -22,49 +22,69 @@
#include "absl/base/nullability.h"
#include "absl/log/check.h"
+#include "absl/status/status.h"
#include "./common/defs.h"
#include "./common/logging.h"
+#include "./common/status_macros.h"
namespace centipede {
-void RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
- const std::string &contents) {
+absl::Status RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
+ const std::string &contents) {
ByteArray contents_ba{contents.cbegin(), contents.cend()};
- RemoteFileAppend(f, contents_ba);
+ return RemoteFileAppend(f, contents_ba);
}
-void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents) {
+absl::Status RemoteFileRead(absl::Nonnull<RemoteFile *> f,
+ std::string &contents) {
ByteArray contents_ba;
- RemoteFileRead(f, contents_ba);
+ RETURN_IF_NOT_OK(RemoteFileRead(f, contents_ba));
contents.assign(contents_ba.cbegin(), contents_ba.cend());
+ return absl::OkStatus();
}
-void RemoteFileSetContents(std::string_view path, const ByteArray &contents) {
- auto *file = RemoteFileOpen(path, "w");
- CHECK(file != nullptr) << VV(path);
- RemoteFileAppend(file, contents);
- RemoteFileClose(file);
+absl::Status RemoteFileSetContents(std::string_view path,
+ const ByteArray &contents) {
+ ASSIGN_OR_RETURN_IF_NOT_OK(RemoteFile * file, RemoteFileOpen(path, "w"));
+ if (file == nullptr) {
+ return absl::UnknownError(
+ "RemoteFileOpen returned an OK status but a nullptr RemoteFile*");
+ }
+ RETURN_IF_NOT_OK(RemoteFileAppend(file, contents));
+ return RemoteFileClose(file);
}
-void RemoteFileSetContents(std::string_view path, const std::string &contents) {
- auto *file = RemoteFileOpen(path, "w");
- CHECK(file != nullptr) << VV(path);
- RemoteFileAppend(file, contents);
- RemoteFileClose(file);
+absl::Status RemoteFileSetContents(std::string_view path,
+ const std::string &contents) {
+ ASSIGN_OR_RETURN_IF_NOT_OK(RemoteFile * file, RemoteFileOpen(path, "w"));
+ if (file == nullptr) {
+ return absl::UnknownError(
+ "RemoteFileOpen returned an OK status but a nullptr RemoteFile*");
+ }
+ RETURN_IF_NOT_OK(RemoteFileAppend(file, contents));
+ RETURN_IF_NOT_OK(RemoteFileClose(file));
+ return absl::OkStatus();
}
-void RemoteFileGetContents(std::string_view path, ByteArray &contents) {
- auto *file = RemoteFileOpen(path, "r");
- CHECK(file != nullptr) << VV(path);
- RemoteFileRead(file, contents);
- RemoteFileClose(file);
+absl::Status RemoteFileGetContents(std::string_view path, ByteArray &contents) {
+ ASSIGN_OR_RETURN_IF_NOT_OK(RemoteFile * file, RemoteFileOpen(path, "r"));
+ if (file == nullptr) {
+ return absl::UnknownError(
+ "RemoteFileOpen returned an OK status but a nullptr RemoteFile*");
+ }
+ RETURN_IF_NOT_OK(RemoteFileRead(file, contents));
+ return RemoteFileClose(file);
}
-void RemoteFileGetContents(std::string_view path, std::string &contents) {
- auto *file = RemoteFileOpen(path, "r");
- CHECK(file != nullptr) << VV(path);
- RemoteFileRead(file, contents);
- RemoteFileClose(file);
+absl::Status RemoteFileGetContents(std::string_view path,
+ std::string &contents) {
+ ASSIGN_OR_RETURN_IF_NOT_OK(RemoteFile * file, RemoteFileOpen(path, "r"));
+ if (file == nullptr) {
+ return absl::UnknownError(
+ "RemoteFileOpen returned an OK status but a nullptr RemoteFile*");
+ }
+ RETURN_IF_NOT_OK(RemoteFileRead(file, contents));
+ return RemoteFileClose(file);
}
} // namespace centipede
diff --git a/common/remote_file.h b/common/remote_file.h
index 6e54190..627109e 100644
--- a/common/remote_file.h
+++ b/common/remote_file.h
@@ -28,6 +28,8 @@
#include <vector>
#include "absl/base/nullability.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
#include "./common/defs.h"
#ifndef CENTIPEDE_DISABLE_RIEGELI
#include "riegeli/bytes/reader.h"
@@ -52,52 +54,58 @@
// Opens a (potentially remote) file 'file_path' and returns a handle to it.
// Supported modes: "r", "a", "w", same as in C FILE API.
-absl::Nullable<RemoteFile *> RemoteFileOpen(std::string_view file_path,
+absl::StatusOr<RemoteFile *> RemoteFileOpen(std::string_view file_path,
const char *mode);
// Closes the file previously opened by RemoteFileOpen.
-void RemoteFileClose(absl::Nonnull<RemoteFile *> f);
+absl::Status RemoteFileClose(absl::Nonnull<RemoteFile *> f);
// Adjusts the buffered I/O capacity for a file opened for writing. By default,
// the internal buffer of size `BUFSIZ` is used. May only be used after opening
// a file, but before performing any other operations on it. Violating this
// requirement in general can cause undefined behavior.
-void RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f, size_t size);
+absl::Status RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f,
+ size_t size);
// Appends bytes from 'ba' to 'f'.
-void RemoteFileAppend(absl::Nonnull<RemoteFile *> f, const ByteArray &ba);
+absl::Status RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
+ const ByteArray &ba);
// Appends characters from 'contents' to 'f'.
-void RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
- const std::string &contents);
+absl::Status RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
+ const std::string &contents);
// Flushes the file's internal buffer. Some dynamic results of a running
// pipeline are consumed by itself (e.g. shard cross-pollination) and can be
// consumed by external processes (e.g. monitoring): for such files, call this
// API after every write to ensure that they are in a valid state.
-void RemoteFileFlush(absl::Nonnull<RemoteFile *> f);
+absl::Status RemoteFileFlush(absl::Nonnull<RemoteFile *> f);
// Reads all current contents of 'f' into 'ba'.
-void RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba);
+absl::Status RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba);
// Reads all current contents of 'f' into 'contents'.
-void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents);
+absl::Status RemoteFileRead(absl::Nonnull<RemoteFile *> f,
+ std::string &contents);
// Creates a (potentially remote) directory 'dir_path', as well as any missing
// parent directories. No-op if the directory already exists.
-void RemoteMkdir(std::string_view dir_path);
+absl::Status RemoteMkdir(std::string_view dir_path);
// Sets the contents of the file at 'path' to 'contents'.
-void RemoteFileSetContents(std::string_view path, const ByteArray &contents);
+absl::Status RemoteFileSetContents(std::string_view path,
+ const ByteArray &contents);
// Sets the contents of the file at 'path' to 'contents'.
-void RemoteFileSetContents(std::string_view path, const std::string &contents);
+absl::Status RemoteFileSetContents(std::string_view path,
+ const std::string &contents);
// Reads the contents of the file at 'path' into 'contents'.
-void RemoteFileGetContents(std::string_view path, ByteArray &contents);
+absl::Status RemoteFileGetContents(std::string_view path, ByteArray &contents);
// Reads the contents of the file at 'path' into 'contents'.
-void RemoteFileGetContents(std::string_view path, std::string &contents);
+absl::Status RemoteFileGetContents(std::string_view path,
+ std::string &contents);
// Returns true if `path` exists.
bool RemotePathExists(std::string_view path);
@@ -106,7 +114,7 @@
bool RemotePathIsDirectory(std::string_view path);
// Returns the size of the file at `path` in bytes. The file must exist.
-int64_t RemoteFileGetSize(std::string_view path);
+absl::StatusOr<int64_t> RemoteFileGetSize(std::string_view path);
// Finds all files matching `glob` and appends them to `matches`.
//
@@ -115,31 +123,32 @@
// be solved in a more specific way, e.g., by listing files in a directory and
// filtering based on some criterion.
[[deprecated("Do not use in new code.")]]
-void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches);
+absl::Status RemoteGlobMatch(std::string_view glob,
+ std::vector<std::string> &matches);
// Lists all files within `path`, recursively expanding subdirectories if
// `recursively` is true. Does not return any directories. Returns an empty
// vector if `path` is an empty directory, or `path` does not exist. Returns
// `{path}` if `path` is a non-directory.
-std::vector<std::string> RemoteListFiles(std::string_view path,
- bool recursively);
+absl::StatusOr<std::vector<std::string>> RemoteListFiles(std::string_view path,
+ bool recursively);
// Renames `from` to `to`.
-void RemotePathRename(std::string_view from, std::string_view to);
+absl::Status RemotePathRename(std::string_view from, std::string_view to);
// Deletes `path`. If `path` is a directory and `recursively` is true,
// recursively deletes all files and subdirectories within `path`.
-void RemotePathDelete(std::string_view path, bool recursively);
+absl::Status RemotePathDelete(std::string_view path, bool recursively);
#ifndef CENTIPEDE_DISABLE_RIEGELI
// Returns a reader for the file at `file_path`.
-std::unique_ptr<riegeli::Reader> CreateRiegeliFileReader(
+absl::StatusOr<std::unique_ptr<riegeli::Reader>> CreateRiegeliFileReader(
std::string_view file_path);
// Returns a writer for the file at `file_path`.
// If `append` is `true`, writes will append to the end of the file if it
// exists. If `false, the file will be truncated to empty if it exists.
-std::unique_ptr<riegeli::Writer> CreateRiegeliFileWriter(
+absl::StatusOr<std::unique_ptr<riegeli::Writer>> CreateRiegeliFileWriter(
std::string_view file_path, bool append);
#endif // CENTIPEDE_DISABLE_RIEGELI
diff --git a/common/remote_file_oss.cc b/common/remote_file_oss.cc
index a49c7c2..38fcaa6 100644
--- a/common/remote_file_oss.cc
+++ b/common/remote_file_oss.cc
@@ -20,8 +20,10 @@
#define FUZZTEST_HAS_OSS_GLOB
#endif // !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__)
+#include <cerrno>
#include <cstdint>
#include <cstdio>
+#include <cstring>
#include <filesystem> // NOLINT
#include <memory>
#include <string>
@@ -33,9 +35,12 @@
#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
#include "./common/defs.h"
#include "./common/logging.h"
#include "./common/remote_file.h"
+#include "./common/status_macros.h"
#ifndef CENTIPEDE_DISABLE_RIEGELI
#include "riegeli/bytes/fd_reader.h"
#include "riegeli/bytes/fd_writer.h"
@@ -48,11 +53,12 @@
class LocalRemoteFile : public RemoteFile {
public:
- static LocalRemoteFile *Create(std::string path, std::string_view mode) {
+ static absl::StatusOr<LocalRemoteFile *> Create(std::string path,
+ std::string_view mode) {
FILE *file = std::fopen(path.c_str(), mode.data());
if (file == nullptr) {
- LOG(ERROR) << "Failed to open file: " << VV(path);
- return nullptr;
+ return absl::UnknownError(absl::StrCat(
+ "fopen() failed, path: ", path, ", errno: ", std::strerror(errno)));
}
return new LocalRemoteFile{std::move(path), file};
}
@@ -67,41 +73,77 @@
LocalRemoteFile(LocalRemoteFile &&) = default;
LocalRemoteFile &operator=(LocalRemoteFile &&) = default;
- void SetWriteBufSize(size_t size) {
- CHECK(write_buf_ == nullptr) << "SetWriteBufCapacity called twice";
+ absl::Status SetWriteBufSize(size_t size) {
+ if (write_buf_ != nullptr) {
+ return absl::FailedPreconditionError("SetWriteBufCapacity called twice");
+ }
write_buf_ = std::make_unique<char[]>(size);
- CHECK_EQ(std::setvbuf(file_, write_buf_.get(), _IOFBF, size), 0)
- << VV(path_);
+ if (std::setvbuf(file_, write_buf_.get(), _IOFBF, size) != 0) {
+ return absl::UnknownError(
+ absl::StrCat("std::setvbuf failed, path: ", path_,
+ ", errno: ", std::strerror(errno)));
+ }
+ return absl::OkStatus();
}
- void Write(const ByteArray &ba) {
+ absl::Status Write(const ByteArray &ba) {
static constexpr auto elt_size = sizeof(ba[0]);
const auto elts_to_write = ba.size();
const auto elts_written =
std::fwrite(ba.data(), elt_size, elts_to_write, file_);
- CHECK_EQ(elts_written, elts_to_write) << VV(path_);
+ if (elts_written != elts_to_write) {
+ return absl::UnknownError(absl::StrCat(
+ "fwrite() wrote less elements that expected, wrote: ", elts_written,
+ ", expected: ", elts_to_write, ", path: ", path_));
+ }
+ return absl::OkStatus();
}
- void Flush() { std::fflush(file_); }
+ absl::Status Flush() {
+ if (std::fflush(file_) != 0) {
+ return absl::UnknownError("fflush() failed");
+ }
+ return absl::OkStatus();
+ }
- void Read(ByteArray &ba) {
+ absl::Status Read(ByteArray &ba) {
// Compute the file size as a difference between the end and start offsets.
- CHECK_EQ(std::fseek(file_, 0, SEEK_END), 0) << VV(path_);
+ if (std::fseek(file_, 0, SEEK_END), 0 != 0) {
+ return absl::UnknownError(absl::StrCat("fseek() failed on path: ", path_,
+ ": ", std::strerror(errno)));
+ }
const auto file_size = std::ftell(file_);
- CHECK_EQ(std::fseek(file_, 0, SEEK_SET), 0) << VV(path_);
+ if (std::fseek(file_, 0, SEEK_SET), 0) {
+ return absl::UnknownError(absl::StrCat("fseek() failed on path: ", path_,
+ ": ", std::strerror(errno)));
+ }
static constexpr auto elt_size = sizeof(ba[0]);
CHECK_EQ(file_size % elt_size, 0)
<< VV(file_size) << VV(elt_size) << VV(path_);
+ if (file_size % elt_size != 0) {
+ return absl::FailedPreconditionError(
+ absl::StrCat("Attempting to read a file with inconsistent element (",
+ elt_size, ") and file size (", file_size, "): ", path_));
+ }
const auto elts_to_read = file_size / elt_size;
ba.resize(elts_to_read);
const auto elts_read = std::fread(ba.data(), elt_size, elts_to_read, file_);
- CHECK_EQ(elts_read, elts_to_read) << VV(path_);
+ if (elts_read != elts_to_read) {
+ return absl::UnknownError(absl::StrCat(
+ "fread() read less elements that expected, wrote: ", elts_read,
+ ", expected: ", elts_to_read, ", path: ", path_));
+ }
+ return absl::OkStatus();
}
- void Close() {
- CHECK_EQ(std::fclose(file_), 0) << VV(path_);
+ absl::Status Close() {
+ if (std::fclose(file_) != 0) {
+ return absl::UnknownError(absl::StrCat("fclose() failed on path: ", path_,
+ ": ", std::strerror(errno)));
+ }
file_ = nullptr;
write_buf_ = nullptr;
+ return absl::OkStatus();
}
private:
@@ -117,38 +159,45 @@
#if defined(FUZZTEST_STUB_STD_FILESYSTEM)
-void RemoteMkdir(std::string_view path) {
+absl::Status RemoteMkdir(std::string_view path) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
-bool RemotePathExists(std::string_view path) {
+absl::Status RemotePathExists(std::string_view path) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
-bool RemotePathIsDirectory(std::string_view path) {
+absl::Status RemotePathIsDirectory(std::string_view path) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
-std::vector<std::string> RemoteListFiles(std::string_view path,
- bool recursively) {
+absl::StatusOr<std::vector<std::string>> RemoteListFiles(std::string_view path,
+ bool recursively) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
-void RemotePathRename(std::string_view from, std::string_view to) {
+absl::Status RemotePathRename(std::string_view from, std::string_view to) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
-void RemotePathDelete(std::string_view path, bool recursively) {
+absl::Status RemotePathDelete(std::string_view path, bool recursively) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}
#else
-void RemoteMkdir(std::string_view path) {
- CHECK(!path.empty());
+absl::Status RemoteMkdir(std::string_view path) {
+ if (path.empty()) {
+ return absl::InvalidArgumentError("Unable to RemoteMkdir() an empty path");
+ }
std::error_code error;
std::filesystem::create_directories(path, error);
- CHECK(!error) << VV(path) << VV(error);
+ if (error) {
+ return absl::UnknownError(
+ absl::StrCat("create_directories() failed, path: ", path,
+ ", error: ", error.message()));
+ }
+ return absl::OkStatus();
}
bool RemotePathExists(std::string_view path) {
@@ -159,9 +208,9 @@
return std::filesystem::is_directory(path);
}
-std::vector<std::string> RemoteListFiles(std::string_view path,
- bool recursively) {
- if (!std::filesystem::exists(path)) return {};
+absl::StatusOr<std::vector<std::string>> RemoteListFiles(std::string_view path,
+ bool recursively) {
+ if (!std::filesystem::exists(path)) return std::vector<std::string>();
auto list_files = [](auto dir_iter) {
std::vector<std::string> ret;
for (const auto &entry : dir_iter) {
@@ -177,20 +226,30 @@
: list_files(std::filesystem::directory_iterator(path));
}
-void RemotePathRename(std::string_view from, std::string_view to) {
+absl::Status RemotePathRename(std::string_view from, std::string_view to) {
std::error_code error;
std::filesystem::rename(from, to, error);
- CHECK(!error) << VV(from) << VV(to) << VV(error);
+ if (error) {
+ return absl::UnknownError(
+ absl::StrCat("filesystem::rename() failed, from: ", from, ", to: ", to,
+ ", error: ", error.message()));
+ }
+ return absl::OkStatus();
}
-void RemotePathDelete(std::string_view path, bool recursively) {
+absl::Status RemotePathDelete(std::string_view path, bool recursively) {
std::error_code error;
if (recursively) {
std::filesystem::remove_all(path, error);
} else {
std::filesystem::remove(path, error);
}
- CHECK(!error) << VV(path) << VV(error);
+ if (error) {
+ return absl::UnknownError(absl::StrCat(
+ "filesystem::remove() or remove_all() failed, path: ", path,
+ ", error: ", error.message()));
+ }
+ return absl::OkStatus();
}
#endif // defined(FUZZTEST_STUB_STD_FILESYSTEM)
@@ -198,38 +257,51 @@
// TODO(ussuri): For now, simulate the old behavior, where a failure to open
// a file returned nullptr. Adjust the clients to expect non-null and use a
// normal ctor with a CHECK instead of `Create()` here instead.
-absl::Nullable<RemoteFile *> RemoteFileOpen(std::string_view path,
+absl::StatusOr<RemoteFile *> RemoteFileOpen(std::string_view path,
const char *mode) {
return LocalRemoteFile::Create(std::string(path), mode);
}
-void RemoteFileClose(absl::Nonnull<RemoteFile *> f) {
+absl::Status RemoteFileClose(absl::Nonnull<RemoteFile *> f) {
auto *file = static_cast<LocalRemoteFile *>(f);
- file->Close();
+ RETURN_IF_NOT_OK(file->Close());
delete file;
+ return absl::OkStatus();
}
-void RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f, size_t size) {
- static_cast<LocalRemoteFile *>(f)->SetWriteBufSize(size);
+absl::Status RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f,
+ size_t size) {
+ return static_cast<LocalRemoteFile *>(f)->SetWriteBufSize(size);
}
-void RemoteFileAppend(absl::Nonnull<RemoteFile *> f, const ByteArray &ba) {
- static_cast<LocalRemoteFile *>(f)->Write(ba);
+absl::Status RemoteFileAppend(absl::Nonnull<RemoteFile *> f,
+ const ByteArray &ba) {
+ return static_cast<LocalRemoteFile *>(f)->Write(ba);
}
-void RemoteFileFlush(absl::Nonnull<RemoteFile *> f) {
- static_cast<LocalRemoteFile *>(f)->Flush();
+absl::Status RemoteFileFlush(absl::Nonnull<RemoteFile *> f) {
+ return static_cast<LocalRemoteFile *>(f)->Flush();
}
-void RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba) {
- static_cast<LocalRemoteFile *>(f)->Read(ba);
+absl::Status RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba) {
+ return static_cast<LocalRemoteFile *>(f)->Read(ba);
}
-int64_t RemoteFileGetSize(std::string_view path) {
+absl::StatusOr<int64_t> RemoteFileGetSize(std::string_view path) {
FILE *f = std::fopen(path.data(), "r");
- CHECK(f != nullptr) << VV(path);
- std::fseek(f, 0, SEEK_END);
+ if (f == nullptr) {
+ return absl::UnknownError(absl::StrCat("fopen() failed, path: ", path,
+ ", errno: ", std::strerror(errno)));
+ }
+ if (std::fseek(f, 0, SEEK_END) != 0) {
+ return absl::UnknownError(absl::StrCat("fseek() failed, path: ", path,
+ ", errno: ", std::strerror(errno)));
+ }
const auto sz = std::ftell(f);
+ if (sz == -1L) {
+ return absl::UnknownError(absl::StrCat("ftell() failed, path: ", path,
+ ", errno: ", std::strerror(errno)));
+ }
std::fclose(f);
return sz;
}
@@ -245,33 +317,41 @@
} // namespace
-void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches) {
+absl::Status RemoteGlobMatch(std::string_view glob,
+ std::vector<std::string> &matches) {
#if defined(FUZZTEST_HAS_OSS_GLOB)
// See `man glob.3`.
::glob_t glob_ret = {};
- CHECK_EQ(
- ::glob(std::string{glob}.c_str(), GLOB_TILDE, HandleGlobError, &glob_ret),
- 0)
- << "Error while globbing glob: " << VV(glob);
+ if (int ret = ::glob(std::string{glob}.c_str(), GLOB_TILDE, HandleGlobError,
+ &glob_ret);
+ ret != 0) {
+ return absl::UnknownError(
+ absl::StrCat("glob() failed, pattern: ", glob, ", returned: ", ret));
+ }
for (int i = 0; i < glob_ret.gl_pathc; ++i) {
matches.emplace_back(glob_ret.gl_pathv[i]);
}
::globfree(&glob_ret);
+ return absl::OkStatus();
#else
LOG(FATAL) << __func__ << "() is not supported on this platform.";
#endif // defined(FUZZTEST_HAS_OSS_GLOB)
}
#ifndef CENTIPEDE_DISABLE_RIEGELI
-std::unique_ptr<riegeli::Reader> CreateRiegeliFileReader(
+absl::StatusOr<std::unique_ptr<riegeli::Reader>> CreateRiegeliFileReader(
std::string_view file_path) {
- return std::make_unique<riegeli::FdReader<>>(file_path);
+ auto ret = std::make_unique<riegeli::FdReader<>>(file_path);
+ RETURN_IF_NOT_OK(ret->status());
+ return ret;
}
-std::unique_ptr<riegeli::Writer> CreateRiegeliFileWriter(
+absl::StatusOr<std::unique_ptr<riegeli::Writer>> CreateRiegeliFileWriter(
std::string_view file_path, bool append) {
- return std::make_unique<riegeli::FdWriter<>>(
+ auto ret = std::make_unique<riegeli::FdWriter<>>(
file_path, riegeli::FdWriterBase::Options().set_append(append));
+ RETURN_IF_NOT_OK(ret->status());
+ return ret;
}
#endif // CENTIPEDE_DISABLE_RIEGELI
diff --git a/common/remote_file_test.cc b/common/remote_file_test.cc
index f6334d7..51ea601 100644
--- a/common/remote_file_test.cc
+++ b/common/remote_file_test.cc
@@ -32,6 +32,8 @@
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
+using ::testing::status::IsOk;
+using ::testing::status::IsOkAndHolds;
void CreateFileOrDie(std::string_view path, std::string_view contents = "") {
std::ofstream f{std::string(path)};
@@ -46,12 +48,14 @@
{
const std::string file_contents1 = "abcd1234";
CreateFileOrDie(file_path, file_contents1);
- EXPECT_EQ(RemoteFileGetSize(file_path), file_contents1.size());
+ EXPECT_THAT(RemoteFileGetSize(file_path),
+ IsOkAndHolds(file_contents1.size()));
}
{
const std::string file_contents2 = "efg567";
- RemoteFileSetContents(file_path, file_contents2);
- EXPECT_EQ(RemoteFileGetSize(file_path), file_contents2.size());
+ ASSERT_THAT(RemoteFileSetContents(file_path, file_contents2), IsOk());
+ EXPECT_THAT(RemoteFileGetSize(file_path),
+ IsOkAndHolds(file_contents2.size()));
}
}
@@ -59,7 +63,7 @@
const fs::path temp_dir = GetTestTempDir(test_info_->name());
const std::string dir_path = temp_dir / "a" / "b" / "c";
- RemoteMkdir(dir_path);
+ ASSERT_THAT(RemoteMkdir(dir_path), IsOk());
EXPECT_TRUE(fs::exists(dir_path));
}
@@ -74,7 +78,7 @@
CreateFileOrDie(file2_path);
EXPECT_THAT(RemoteListFiles(temp_dir.string(), /*recursively=*/false),
- UnorderedElementsAre(file1_path));
+ IsOkAndHolds(UnorderedElementsAre(file1_path)));
}
TEST(RemoteListFiles, ListsFilesInRecursiveDirectories) {
@@ -90,14 +94,15 @@
const std::string file3_path = dir1_path / "file_03";
CreateFileOrDie(file3_path);
- EXPECT_THAT(RemoteListFiles(temp_dir.string(), /*recursively=*/true),
- UnorderedElementsAre(file1_path, file2_path, file3_path));
+ EXPECT_THAT(
+ RemoteListFiles(temp_dir.string(), /*recursively=*/true),
+ IsOkAndHolds(UnorderedElementsAre(file1_path, file2_path, file3_path)));
}
TEST(RemoteListFiles, ReturnsAnEmptyResultWhenNoFilesAreFound) {
const fs::path temp_dir = GetTestTempDir(test_info_->name());
EXPECT_THAT(RemoteListFiles(temp_dir.string(), /*recursively=*/false),
- IsEmpty());
+ IsOkAndHolds(IsEmpty()));
}
TEST(RemoteListFiles, ReturnsASingleFileWhenListingAFile) {
@@ -107,13 +112,13 @@
CreateFileOrDie(file1_path);
EXPECT_THAT(RemoteListFiles(temp_dir.string(), /*recursively=*/false),
- UnorderedElementsAre(file1_path));
+ IsOkAndHolds(UnorderedElementsAre(file1_path)));
}
TEST(RemoteListFiles, ReturnsAnEmptyVectorWhenPathDoesNotExist) {
EXPECT_THAT(
RemoteListFiles("/this/file/path/does/not/exist", /*recursively=*/false),
- IsEmpty());
+ IsOkAndHolds(IsEmpty()));
}
TEST(RemotePathDelete, RecursivelyDeletesAllFilesAndSubdirectories) {
@@ -123,7 +128,8 @@
const std::string file_path = a_b_c / "file";
CreateFileOrDie(file_path);
- RemotePathDelete(temp_dir.string(), /*recursively=*/true);
+ ASSERT_THAT(RemotePathDelete(temp_dir.string(), /*recursively=*/true),
+ IsOk());
EXPECT_FALSE(fs::exists(a_b_c));
}
diff --git a/common/status_macros.h b/common/status_macros.h
new file mode 100644
index 0000000..48c9dd2
--- /dev/null
+++ b/common/status_macros.h
@@ -0,0 +1,64 @@
+// Copyright 2024 The Centipede Authors.
+//
+// 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
+//
+// https://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.
+
+// Convenience macros for dealing with absl::Status and friends.
+
+#ifndef FUZZTEST_COMMON_STATUS_MACROS_H_
+#define FUZZTEST_COMMON_STATUS_MACROS_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/optimization.h"
+#include "absl/log/log.h"
+#include "absl/types/source_location.h"
+
+// If `status_expr` (an expression of type `absl::Status`) is not OK then return
+// it from the current function. Otherwise, do nothing.
+#define RETURN_IF_NOT_OK(status_expr) \
+ do { \
+ const absl::Status status_value = (status_expr); \
+ if (ABSL_PREDICT_FALSE(!status_value.ok())) { \
+ return status_value; \
+ } \
+ } while (false)
+
+// Assigns `dest` to the value contained within the `absl::StatusOr<T> src` if
+// `src.ok()`, otherwise, returns `src.status()` from the current function.
+#define ASSIGN_OR_RETURN_IF_NOT_OK(dest, src) \
+ ASSIGN_OR_RETURN_IF_NOT_OK_IMPL_( \
+ CHECKS_INTERNAL_CONCAT_(value_or_, __LINE__), dest, src)
+#define ASSIGN_OR_RETURN_IF_NOT_OK_IMPL_(value_or, dest, src) \
+ auto value_or = (src); \
+ if (ABSL_PREDICT_FALSE(!value_or.ok())) { \
+ return std::move(value_or).status(); \
+ } \
+ dest = std::move(value_or).value()
+
+// Internal helper for concatenating macro values.
+#define CHECKS_INTERNAL_CONCAT_IMPL_(x, y) x##y
+#define CHECKS_INTERNAL_CONCAT_(x, y) CHECKS_INTERNAL_CONCAT_IMPL_(x, y)
+
+namespace centipede {
+template <typename T>
+decltype(auto) ValueOrDie(
+ T&& value ABSL_ATTRIBUTE_LIFETIME_BOUND,
+ absl::SourceLocation loc = absl::SourceLocation::current()) {
+ if (ABSL_PREDICT_FALSE(!value.ok())) {
+ LOG(FATAL).AtLocation(loc)
+ << "ValueOrDie on non-OK status: " << value.status();
+ }
+ return *std::forward<T>(value);
+}
+} // namespace centipede
+
+#endif // FUZZTEST_COMMON_STATUS_MACROS_H_
diff --git a/fuzztest/internal/io.cc b/fuzztest/internal/io.cc
index e351712..eca94f9 100644
--- a/fuzztest/internal/io.cc
+++ b/fuzztest/internal/io.cc
@@ -253,7 +253,11 @@
// file and a file that is not a blob file. Once we can, we should not fall
// back to reading the file directly if it is an empty blob file.
std::string contents;
- centipede::RemoteFileGetContents(file_path, contents);
+ const absl::Status get_contents_status =
+ centipede::RemoteFileGetContents(file_path, contents);
+ FUZZTEST_INTERNAL_CHECK_PRECONDITION(
+ get_contents_status.ok(), "RemoteFileGetContents failed on ", file_path,
+ ", status: ", get_contents_status.message());
absl::Status result = consume(file_path, std::nullopt, std::move(contents));
if (result.ok()) {
++total_loaded_inputs;