Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No public description #976

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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_
Loading