Skip to content

Commit

Permalink
No public description
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 604846219
  • Loading branch information
lszekeres authored and copybara-github committed Feb 7, 2024
1 parent cb186da commit 6b47255
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 79 deletions.
1 change: 1 addition & 0 deletions centipede/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ cc_library(
":disable_riegeli": ["CENTIPEDE_DISABLE_RIEGELI"],
"//conditions:default": [],
}),
visibility = EXTENDED_API_VISIBILITY,
deps = [
":defs",
":logging",
Expand Down
14 changes: 14 additions & 0 deletions centipede/remote_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ ABSL_ATTRIBUTE_WEAK bool RemotePathExists(std::string_view path) {
return std::filesystem::exists(path);
}

ABSL_ATTRIBUTE_WEAK bool RemotePathIsDirectory(std::string_view path) {
return std::filesystem::is_directory(path);
}

ABSL_ATTRIBUTE_WEAK int64_t RemoteFileGetSize(std::string_view path) {
FILE *f = std::fopen(path.data(), "r");
CHECK(f != nullptr) << VV(path);
Expand Down Expand Up @@ -171,6 +175,16 @@ ABSL_ATTRIBUTE_WEAK void RemoteGlobMatch(std::string_view glob,
::globfree(&glob_ret);
}

ABSL_ATTRIBUTE_WEAK std::vector<std::string> RemoteListDirectory(
std::string_view path) {
if (!std::filesystem::is_directory(path)) return {};
std::vector<std::string> ret;
for (const auto &entry : std::filesystem::directory_iterator(path)) {
ret.push_back(entry.path());
}
return ret;
}

ABSL_ATTRIBUTE_WEAK std::vector<std::string> RemoteListFilesRecursively(
std::string_view path) {
if (!std::filesystem::exists(path)) return {};
Expand Down
7 changes: 7 additions & 0 deletions centipede/remote_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,19 @@ void RemoteFileGetContents(const std::filesystem::path &path,
// Returns true if `path` exists.
bool RemotePathExists(std::string_view path);

// Returns true if `path` is a directory.
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);

// Finds all files matching `glob` and appends them to `matches`.
void RemoteGlobMatch(std::string_view glob, std::vector<std::string> &matches);

// Returns a list of top-level paths under `path`. If `path` is not a directory,
// or it's an empty directory, returns an empty list.
std::vector<std::string> RemoteListDirectory(std::string_view path);

// Recursively lists all files within `path`. 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.
Expand Down
1 change: 1 addition & 0 deletions fuzztest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ cc_library(
"@com_google_absl//absl/hash",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/strings:string_view",
"@com_google_fuzztest//centipede:remote_file",
],
)

Expand Down
134 changes: 69 additions & 65 deletions fuzztest/internal/io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@

#include "./fuzztest/internal/io.h"

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <optional>
#include <sstream>
#include <string>
Expand All @@ -30,6 +25,7 @@
#include "absl/hash/hash.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "./centipede/remote_file.h"
#include "./fuzztest/internal/logging.h"

#if defined(__APPLE__)
Expand All @@ -39,55 +35,81 @@
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0)
// std::filesystem requires macOS 10.15+ or iOS 13+.
// Just stub out these functions.
#define STUB_FILESYSTEM
#define FUZZTEST_STUB_FILESYSTEM
#endif
#endif

namespace fuzztest::internal {

#if defined(STUB_FILESYSTEM)
#if defined(FUZZTEST_STUB_FILESYSTEM)

bool WriteFile(absl::string_view filename, absl::string_view contents) {
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
bool WriteFile(absl::string_view path, absl::string_view contents) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

std::string WriteDataToDir(absl::string_view data, absl::string_view dir) {
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
std::optional<std::string> ReadFile(absl::string_view path) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

std::vector<FilePathAndData> ReadFileOrDirectory(
absl::string_view file_or_dir) {
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
bool IsDirectory(absl::string_view path) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

std::optional<std::string> ReadFile(absl::string_view file) {
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
bool CreateDirectory(absl::string_view path) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

std::vector<std::string> ListDirectory(absl::string_view dir) {
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
std::vector<std::string> ListDirectory(absl::string_view path) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

#else // defined(__APPLE__)
std::vector<std::string> ListDirectoryRecursively(absl::string_view path) {
FUZZTEST_INTERNAL_CHECK(false, "Filesystem API not supported in iOS/MacOS");
}

bool WriteFile(absl::string_view filename, absl::string_view contents) {
std::filesystem::path file_path{
std::string_view{filename.data(), filename.size()}};
#else // FUZZTEST_STUB_FILESYSTEM

bool WriteFile(absl::string_view path, absl::string_view contents) {
// Just in case the directory does not currently exist.
// If it does, this is a noop.
std::filesystem::create_directories(file_path.parent_path());

std::ofstream file(file_path);
file << contents;
file.close();
if (!file.good()) {
absl::FPrintF(GetStderr(), "%s:%d: Error writing %s: (%d) %s\n", __FILE__,
__LINE__, filename, errno, strerror(errno));
if (!CreateDirectory(Dirname(path))) {
absl::FPrintF(GetStderr(), "[!] %s:%d: Couldn't create directory: %s\n",
__FILE__, __LINE__, path);
return false;
}
centipede::RemoteFileSetContents(path, std::string(contents));
return true;
}

std::optional<std::string> ReadFile(absl::string_view path) {
std::string contents;
if (!centipede::RemotePathExists(path)) {
absl::FPrintF(GetStderr(), "[!] %s:%d: File doesn't exist: %s\n", __FILE__,
__LINE__, path);
return std::nullopt;
}
return !file.fail();
centipede::RemoteFileGetContents(path, contents);
return contents;
}

bool IsDirectory(absl::string_view path) {
return centipede::RemotePathIsDirectory(path);
}

bool CreateDirectory(absl::string_view path) {
centipede::RemoteMkdir(path);
return true;
}

std::vector<std::string> ListDirectory(absl::string_view path) {
return centipede::RemoteListDirectory(path);
}

std::vector<std::string> ListDirectoryRecursively(absl::string_view path) {
return centipede::RemoteListFilesRecursively(path);
}

#endif // FUZZTEST_STUB_FILESYSTEM

std::string WriteDataToDir(absl::string_view data, absl::string_view outdir) {
std::string filename(outdir);
if (filename.back() != '/') filename += '/';
Expand All @@ -97,53 +119,35 @@ std::string WriteDataToDir(absl::string_view data, absl::string_view outdir) {
return filename;
}

std::optional<std::string> ReadFile(absl::string_view file) {
std::filesystem::path file_path{std::string_view{file.data(), file.size()}};
if (!std::filesystem::is_regular_file(file_path)) return std::nullopt;
std::ifstream stream(file_path);
if (!stream.good()) {
absl::FPrintF(stderr, "%s:%d: Error reading %s: (%d) %s\n", __FILE__,
__LINE__, file, errno, strerror(errno));
return std::nullopt;
}
std::stringstream buffer;
buffer << stream.rdbuf();
return buffer.str();
}

std::vector<FilePathAndData> ReadFileOrDirectory(
absl::string_view file_or_dir) {
std::vector<FilePathAndData> out;

const auto try_append_file = [&](std::string path) {
std::optional<std::string> data = ReadFile(path);
if (data.has_value()) {
out.push_back(FilePathAndData{std::move(path), *std::move(data)});
std::optional<std::string> contents = ReadFile(path);
if (contents.has_value()) {
out.push_back(FilePathAndData{std::move(path), *std::move(contents)});
}
};
std::filesystem::path file_or_dir_path{
std::string_view{file_or_dir.data(), file_or_dir.size()}};
if (std::filesystem::is_directory(file_or_dir_path)) {
for (const auto& entry :
std::filesystem::recursive_directory_iterator(file_or_dir_path)) {
try_append_file(entry.path().string());
if (IsDirectory(file_or_dir)) {
for (const auto& path : ListDirectoryRecursively(file_or_dir)) {
if (!IsDirectory(path)) {
try_append_file(path);
}
}
} else {
try_append_file(std::string(file_or_dir));
}
return out;
}

std::vector<std::string> ListDirectory(absl::string_view dir) {
std::vector<std::string> out;
std::filesystem::path dir_path{std::string_view{dir.data(), dir.size()}};
if (!std::filesystem::is_directory(dir_path)) return out;
for (const auto& entry : std::filesystem::directory_iterator(dir_path)) {
out.push_back(entry.path().string());
}
return out;
}
absl::string_view Dirname(absl::string_view filename) {
auto last_slash_pos = filename.find_last_of("/\\");

#endif // defined(STUB_FILESYSTEM)
return last_slash_pos == absl::string_view::npos
? filename
: filename.substr(0, last_slash_pos);
}

absl::string_view Basename(absl::string_view filename) {
auto last_slash_pos = filename.find_last_of("/\\");
Expand Down
43 changes: 29 additions & 14 deletions fuzztest/internal/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,53 @@

namespace fuzztest::internal {

bool WriteFile(absl::string_view filename, absl::string_view contents);
// Writes `contents` to the file at `path`. Returns true on success, false
// otherwise.
bool WriteFile(absl::string_view path, absl::string_view contents);

// Returns the contents of the file at `path` or std::nullopt on failure.
std::optional<std::string> ReadFile(absl::string_view path);

// Returns true if `path` is a directory, false otherwise.
bool IsDirectory(absl::string_view path);

// Creates directory at `path`, *recursively* creating parent directories if
// necessary. Returns true on success, false otherwise.
bool CreateDirectory(absl::string_view path);

// Returns a list of top-level paths under `path`. If `path` is not a directory,
// or it's an empty directory, returns an empty list.
std::vector<std::string> ListDirectory(absl::string_view path);

// Returns all paths under `path` *recursively*. If `path` is not a directory,
// returns an empty list.
std::vector<std::string> ListDirectoryRecursively(absl::string_view path);

// Write `data` to its hash-based filename in `dir`. Returns the `dir`-appended
// path to the file.
std::string WriteDataToDir(absl::string_view data, absl::string_view dir);

// Reads `file` and returns its content. If `file` is not a regular file or
// reading it fails, returns `std::nullopt`.
std::optional<std::string> ReadFile(absl::string_view file);

struct FilePathAndData {
std::string path;
std::string data;
};

// If `file_or_dir` is a directory, returns a list of its files' paths and
// contents. If `file_or_dir` is a file, returns a singleton list with its path
// and content. In all other cases, returns an empty list.
// contents *recursively*. If `file_or_dir` is a file, returns a singleton list
// with its path and content. In all other cases, returns an empty list.
std::vector<FilePathAndData> ReadFileOrDirectory(absl::string_view file_or_dir);

// Returns a list of top-level paths in `dir`. If `dir` is not a directory,
// returns an empty list.
std::vector<std::string> ListDirectory(absl::string_view dir);

// Returns the basename of `filename`.
absl::string_view Basename(absl::string_view filename);

// Reads files as strings from the directory `dir` and returns a vector usable
// by .WithSeeds().
std::vector<std::tuple<std::string>> ReadFilesFromDirectory(
absl::string_view dir);

// Returns the dirname of `filename`.
absl::string_view Dirname(absl::string_view filename);

// Returns the basename of `filename`.
absl::string_view Basename(absl::string_view filename);

} // namespace fuzztest::internal

#endif // FUZZTEST_FUZZTEST_INTERNAL_IO_H_

0 comments on commit 6b47255

Please sign in to comment.