Fix build issues on old versions of iOS/MacOS. - 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
diff --git a/centipede/binary_info.cc b/centipede/binary_info.cc index 2c2ba14..073e508 100644 --- a/centipede/binary_info.cc +++ b/centipede/binary_info.cc
@@ -123,13 +123,14 @@ 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); @@ -139,12 +140,13 @@ 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()); }
diff --git a/centipede/config_file.cc b/centipede/config_file.cc index 6bc80b2..c03df11 100644 --- a/centipede/config_file.cc +++ b/centipede/config_file.cc
@@ -162,7 +162,7 @@ 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(); @@ -170,7 +170,7 @@ 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()); @@ -244,7 +244,7 @@ } else { file_contents = flags_str; } - RemoteFileSetContents(path, file_contents); + RemoteFileSetContents(path.c_str(), file_contents); } return path;
diff --git a/centipede/seed_corpus_maker_lib.cc b/centipede/seed_corpus_maker_lib.cc index c35417e..b43d7e9 100644 --- a/centipede/seed_corpus_maker_lib.cc +++ b/centipede/seed_corpus_maker_lib.cc
@@ -501,8 +501,9 @@ /*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;
diff --git a/centipede/util.cc b/centipede/util.cc index cd972a2..ba33dac 100644 --- a/centipede/util.cc +++ b/centipede/util.cc
@@ -146,7 +146,7 @@ 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); }
diff --git a/common/remote_file.cc b/common/remote_file.cc index 63d95fc..eb761e6 100644 --- a/common/remote_file.cc +++ b/common/remote_file.cc
@@ -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" @@ -39,33 +39,29 @@ 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);
diff --git a/common/remote_file.h b/common/remote_file.h index daf6a36..34e5d43 100644 --- a/common/remote_file.h +++ b/common/remote_file.h
@@ -22,7 +22,6 @@ #include <cstddef> #include <cstdint> -#include <filesystem> // NOLINT #include <memory> #include <string> #include <string_view> @@ -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. @@ -78,20 +88,16 @@ 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);
diff --git a/common/remote_file_oss.cc b/common/remote_file_oss.cc index 8229c35..826df7d 100644 --- a/common/remote_file_oss.cc +++ b/common/remote_file_oss.cc
@@ -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> @@ -121,6 +122,31 @@ } // 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; @@ -128,75 +154,10 @@ CHECK(!error) << VV(path) << VV(error); } -// 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, - const char *mode) { - return LocalRemoteFile::Create(std::string(path), mode); -} - -void RemoteFileClose(absl::Nonnull<RemoteFile *> f) { - auto *file = static_cast<LocalRemoteFile *>(f); - file->Close(); - delete file; -} - -void RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f, size_t size) { - static_cast<LocalRemoteFile *>(f)->SetWriteBufSize(size); -} - -void RemoteFileAppend(absl::Nonnull<RemoteFile *> f, const ByteArray &ba) { - static_cast<LocalRemoteFile *>(f)->Write(ba); -} - -void RemoteFileFlush(absl::Nonnull<RemoteFile *> f) { - static_cast<LocalRemoteFile *>(f)->Flush(); -} - -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); - std::fseek(f, 0, SEEK_END); - const auto sz = std::ftell(f); - std::fclose(f); - return sz; -} - -namespace { - -int HandleGlobError(const char *epath, int eerrno) { - LOG(FATAL) << "Error while globbing path: " << VV(epath) << VV(eerrno); - return -1; -} - -} // namespace - -void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches) { -#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__Fuchsia__) - // 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); - for (int i = 0; i < glob_ret.gl_pathc; ++i) { - matches.emplace_back(glob_ret.gl_pathv[i]); - } - ::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 {}; @@ -231,6 +192,75 @@ 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. +absl::Nullable<RemoteFile *> RemoteFileOpen(std::string_view path, + const char *mode) { + return LocalRemoteFile::Create(std::string(path), mode); +} + +void RemoteFileClose(absl::Nonnull<RemoteFile *> f) { + auto *file = static_cast<LocalRemoteFile *>(f); + file->Close(); + delete file; +} + +void RemoteFileSetWriteBufferSize(absl::Nonnull<RemoteFile *> f, size_t size) { + static_cast<LocalRemoteFile *>(f)->SetWriteBufSize(size); +} + +void RemoteFileAppend(absl::Nonnull<RemoteFile *> f, const ByteArray &ba) { + static_cast<LocalRemoteFile *>(f)->Write(ba); +} + +void RemoteFileFlush(absl::Nonnull<RemoteFile *> f) { + static_cast<LocalRemoteFile *>(f)->Flush(); +} + +void RemoteFileRead(absl::Nonnull<RemoteFile *> f, ByteArray &ba) { + static_cast<LocalRemoteFile *>(f)->Read(ba); +} + +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); + const auto sz = std::ftell(f); + std::fclose(f); + return sz; +} + +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(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); + for (int i = 0; i < glob_ret.gl_pathc; ++i) { + matches.emplace_back(glob_ret.gl_pathv[i]); + } + ::globfree(&glob_ret); +#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( std::string_view file_path) {
diff --git a/fuzztest/internal/io.cc b/fuzztest/internal/io.cc index 864c2be..ef66cb4 100644 --- a/fuzztest/internal/io.cc +++ b/fuzztest/internal/io.cc
@@ -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> @@ -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. @@ -150,7 +150,7 @@ 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);