Skip to content

Commit

Permalink
Fix build issues on old versions of iOS/MacOS.
Browse files Browse the repository at this point in the history
-  I removed `std::filesystem` usages in the API definitions.
-  I stubbed out implementations that directly depend on `std::filesystem`.

I also did a few cosmetic changes to stubbing out the OSS glob implementation
for Windows/Android/Fuchsia.

Note that the FUZZTEST_STUB_STD_FILESYSTEM macro is currently defined in two
places. This is temporary and will be removed in the following CL.

PiperOrigin-RevId: 648452942
  • Loading branch information
fniksic authored and copybara-github committed Jul 1, 2024
1 parent e576caa commit 6516f9c
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 80 deletions.
14 changes: 8 additions & 6 deletions centipede/binary_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,14 @@ void BinaryInfo::InitializeFromSanCovBinary(
void BinaryInfo::Read(std::string_view dir) {
std::string symbol_table_contents;
// TODO(b/295978603): move calculation of paths into WorkDir class.
RemoteFileGetContents(std::filesystem::path(dir).append(kSymbolTableFileName),
symbol_table_contents);
RemoteFileGetContents(
(std::filesystem::path(dir) / kSymbolTableFileName).c_str(),
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).append(kPCTableFileName),
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);
Expand All @@ -139,12 +140,13 @@ void BinaryInfo::Write(std::string_view dir) {
std::ostringstream symbol_table_stream;
symbols.WriteToLLVMSymbolizer(symbol_table_stream);
// TODO(b/295978603): move calculation of paths into WorkDir class.
RemoteFileSetContents(std::filesystem::path(dir).append(kSymbolTableFileName),
symbol_table_stream.str());
RemoteFileSetContents(
(std::filesystem::path(dir) / kSymbolTableFileName).c_str(),
symbol_table_stream.str());

std::ostringstream pc_table_stream;
WritePcTable(pc_table, pc_table_stream);
RemoteFileSetContents(std::filesystem::path(dir).append(kPCTableFileName),
RemoteFileSetContents((std::filesystem::path(dir) / kPCTableFileName).c_str(),
pc_table_stream.str());
}

Expand Down
6 changes: 3 additions & 3 deletions centipede/config_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ AugmentedArgvWithCleanup LocalizeConfigFilesInArgv(
if (!path.empty() && !std::filesystem::exists(path)) { // assume remote
// Read the remote file.
std::string contents;
RemoteFileGetContents(path, contents);
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, contents);
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());
Expand Down Expand Up @@ -244,7 +244,7 @@ set -x
} else {
file_contents = flags_str;
}
RemoteFileSetContents(path, file_contents);
RemoteFileSetContents(path.c_str(), file_contents);
}

return path;
Expand Down
5 changes: 3 additions & 2 deletions centipede/seed_corpus_maker_lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,9 @@ void GenerateSeedCorpusFromConfig( //
/*my_shard_index=*/0,
};
const std::filesystem::path debug_info_dir = workdir.DebugInfoDirPath();
RemoteMkdir(debug_info_dir.string());
RemoteFileSetContents(debug_info_dir / "seeding.cfg", absl::StrCat(config));
RemoteMkdir(debug_info_dir.c_str());
RemoteFileSetContents((debug_info_dir / "seeding.cfg").c_str(),
absl::StrCat(config));

InputAndFeaturesVec elements;

Expand Down
2 changes: 1 addition & 1 deletion centipede/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ void WriteToRemoteHashedFileInDir(std::string_view dir_path, ByteSpan data) {
std::string HashOfFileContents(std::string_view file_path) {
if (file_path.empty()) return "";
std::string file_contents;
RemoteFileGetContents(std::filesystem::path(file_path), file_contents);
RemoteFileGetContents(file_path, file_contents);
return Hash(file_contents);
}

Expand Down
22 changes: 9 additions & 13 deletions common/remote_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

#include "./common/remote_file.h"

#include <filesystem> // NOLINT
#include <string>
#include <string_view>

#include "absl/base/nullability.h"
#include "absl/log/check.h"
Expand All @@ -39,33 +39,29 @@ void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents) {
contents.assign(contents_ba.cbegin(), contents_ba.cend());
}

void RemoteFileSetContents(const std::filesystem::path &path,
const ByteArray &contents) {
auto *file = RemoteFileOpen(path.string(), "w");
void RemoteFileSetContents(std::string_view path, const ByteArray &contents) {
auto *file = RemoteFileOpen(path, "w");
CHECK(file != nullptr) << VV(path);
RemoteFileAppend(file, contents);
RemoteFileClose(file);
}

void RemoteFileSetContents(const std::filesystem::path &path,
const std::string &contents) {
auto *file = RemoteFileOpen(path.string(), "w");
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);
}

void RemoteFileGetContents(const std::filesystem::path &path,
ByteArray &contents) {
auto *file = RemoteFileOpen(path.string(), "r");
void RemoteFileGetContents(std::string_view path, ByteArray &contents) {
auto *file = RemoteFileOpen(path, "r");
CHECK(file != nullptr) << VV(path);
RemoteFileRead(file, contents);
RemoteFileClose(file);
}

void RemoteFileGetContents(const std::filesystem::path &path,
std::string &contents) {
auto *file = RemoteFileOpen(path.string(), "r");
void RemoteFileGetContents(std::string_view path, std::string &contents) {
auto *file = RemoteFileOpen(path, "r");
CHECK(file != nullptr) << VV(path);
RemoteFileRead(file, contents);
RemoteFileClose(file);
Expand Down
24 changes: 15 additions & 9 deletions common/remote_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

#include <cstddef>
#include <cstdint>
#include <filesystem> // NOLINT
#include <memory>
#include <string>
#include <string_view>
Expand All @@ -35,6 +34,17 @@
#include "riegeli/bytes/writer.h"
#endif // CENTIPEDE_DISABLE_RIEGELI

#if defined(__APPLE__)
#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_15) || \
(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0)
// std::filesystem requires macOS 10.15+ or iOS 13+.
// Use this macro to stub out code that depends on std::filesystem.
#define FUZZTEST_STUB_STD_FILESYSTEM
#endif
#endif

namespace centipede {

// An opaque file handle.
Expand Down Expand Up @@ -78,20 +88,16 @@ void RemoteFileRead(absl::Nonnull<RemoteFile *> f, std::string &contents);
void RemoteMkdir(std::string_view dir_path);

// Sets the contents of the file at 'path' to 'contents'.
void RemoteFileSetContents(const std::filesystem::path &path,
const ByteArray &contents);
void RemoteFileSetContents(std::string_view path, const ByteArray &contents);

// Sets the contents of the file at 'path' to 'contents'.
void RemoteFileSetContents(const std::filesystem::path &path,
const std::string &contents);
void RemoteFileSetContents(std::string_view path, const std::string &contents);

// Reads the contents of the file at 'path' into 'contents'.
void RemoteFileGetContents(const std::filesystem::path &path,
ByteArray &contents);
void RemoteFileGetContents(std::string_view path, ByteArray &contents);

// Reads the contents of the file at 'path' into 'contents'.
void RemoteFileGetContents(const std::filesystem::path &path,
std::string &contents);
void RemoteFileGetContents(std::string_view path, std::string &contents);

// Returns true if `path` exists.
bool RemotePathExists(std::string_view path);
Expand Down
110 changes: 70 additions & 40 deletions common/remote_file_oss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__)
#include <glob.h>
#define FUZZTEST_HAS_OSS_GLOB
#endif // !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__)

#include <cstdint>
Expand Down Expand Up @@ -121,13 +122,78 @@ class LocalRemoteFile : public RemoteFile {

} // namespace

#if defined(FUZZTEST_STUB_STD_FILESYSTEM)

void RemoteMkdir(std::string_view path) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}

bool RemotePathExists(std::string_view path) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}

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) {
LOG(FATAL) << "Filesystem API not supported in iOS/MacOS";
}

void 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());
std::error_code error;
std::filesystem::create_directories(path, error);
CHECK(!error) << VV(path) << VV(error);
}

bool RemotePathExists(std::string_view path) {
return std::filesystem::exists(path);
}

std::vector<std::string> RemoteListFiles(std::string_view path,
bool recursively) {
if (!std::filesystem::exists(path)) return {};
auto list_files = [](auto dir_iter) {
std::vector<std::string> ret;
for (const auto &entry : dir_iter) {
if (entry.is_directory()) continue;
// On Windows, there's no implicit conversion from `std::filesystem::path`
// to `std::string`.
ret.push_back(entry.path().string());
}
return ret;
};
return recursively
? list_files(std::filesystem::recursive_directory_iterator(path))
: list_files(std::filesystem::directory_iterator(path));
}

void 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);
}

void 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);
}

#endif // defined(FUZZTEST_STUB_STD_FILESYSTEM)

// 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.
Expand Down Expand Up @@ -158,10 +224,6 @@ void RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba) {
static_cast<LocalRemoteFile *>(f)->Read(ba);
}

bool RemotePathExists(std::string_view path) {
return std::filesystem::exists(path);
}

int64_t RemoteFileGetSize(std::string_view path) {
FILE *f = std::fopen(path.data(), "r");
CHECK(f != nullptr) << VV(path);
Expand All @@ -173,15 +235,17 @@ int64_t RemoteFileGetSize(std::string_view path) {

namespace {

#if defined(FUZZTEST_HAS_OSS_GLOB)
int HandleGlobError(const char *epath, int eerrno) {
LOG(FATAL) << "Error while globbing path: " << VV(epath) << VV(eerrno);
return -1;
}
#endif // defined(FUZZTEST_HAS_OSS_GLOB)

} // namespace

void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches) {
#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__)
#if defined(FUZZTEST_HAS_OSS_GLOB)
// See `man glob.3`.
::glob_t glob_ret = {};
CHECK_EQ(
Expand All @@ -194,41 +258,7 @@ void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches) {
::globfree(&glob_ret);
#else
LOG(FATAL) << __func__ << "() is not supported on this platform.";
#endif // !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__)
}

std::vector<std::string> RemoteListFiles(std::string_view path,
bool recursively) {
if (!std::filesystem::exists(path)) return {};
auto list_files = [](auto dir_iter) {
std::vector<std::string> ret;
for (const auto &entry : dir_iter) {
if (entry.is_directory()) continue;
// On Windows, there's no implicit conversion from `std::filesystem::path`
// to `std::string`.
ret.push_back(entry.path().string());
}
return ret;
};
return recursively
? list_files(std::filesystem::recursive_directory_iterator(path))
: list_files(std::filesystem::directory_iterator(path));
}

void 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);
}

void 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);
#endif // defined(FUZZTEST_HAS_OSS_GLOB)
}

#ifndef CENTIPEDE_DISABLE_RIEGELI
Expand Down
12 changes: 6 additions & 6 deletions fuzztest/internal/io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
#include "./fuzztest/internal/io.h"

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <filesystem> // NOLINT
#include <fstream>
#include <optional>
#include <sstream>
Expand All @@ -32,20 +31,21 @@
#include "absl/strings/string_view.h"
#include "./fuzztest/internal/logging.h"

// TODO(fniksic): Remove this definition once we include remote_file.h.
#if defined(__APPLE__)
#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_15) || \
(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0)
// std::filesystem requires macOS 10.15+ or iOS 13+.
// Just stub out these functions.
#define FUZZTEST_STUB_FILESYSTEM
// Use this macro to stub out code that depends on std::filesystem.
#define FUZZTEST_STUB_STD_FILESYSTEM
#endif
#endif

namespace fuzztest::internal {

#if defined(FUZZTEST_STUB_FILESYSTEM)
#if defined(FUZZTEST_STUB_STD_FILESYSTEM)

// TODO(lszekeres): Return absl::Status instead of bool for these.

Expand Down Expand Up @@ -150,7 +150,7 @@ std::vector<std::string> ListDirectoryRecursively(absl::string_view path) {
return output_paths;
}

#endif // FUZZTEST_STUB_FILESYSTEM
#endif // FUZZTEST_STUB_STD_FILESYSTEM

std::string WriteDataToDir(absl::string_view data, absl::string_view outdir) {
std::string filename(outdir);
Expand Down

0 comments on commit 6516f9c

Please sign in to comment.