2017-08-22 07:25:50 +08:00
|
|
|
//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-08-22 07:25:50 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IO functions implementation using Posix API.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FuzzerDefs.h"
|
[libFuzzer] Add support for Fuchsia OS.
Summary:
This patch adds the initial support for Fuchsia.
- LIBFUZZER_FUCHSIA is added as an OS type in FuzzerDefs.h
- Fuchsia is, by design, not POSIX compliant. However, it does use ELF and
supports common POSIX I/O functions. Thus, FuzzerExtFunctions.h and
FuzzerIO.h are implemented by extending the header guards in
FuzzerExtFunctionsWeak.cpp and FuzzerIOPosix.cpp to include
LIBFUZZER_FUCHSIA.
- The platform-specific portions of FuzzerUtil.h are implemented by
FuzzerUtilFuchsia.cpp, which makes use of exception ports, syscalls, and
the launchpad library.
- The experimental equivalence server is not currently supported, so
FuzzerShmem.h is implemented by stub methods in FuzzerShmemFuchsia.cpp.
Any future implementation will likely involve VMOs.
Tested with ASAN/SanCov on Fuchsia/x86-64 with the canonical toy fuzzer.
Patch By: aarongreen
Reviewers: kcc, morehouse, flowerhack, phosek
Reviewed By: kcc, phosek, Eugene.Zelenko
Subscribers: srhines, mgorny, Eugene.Zelenko
Differential Revision: https://reviews.llvm.org/D40974
llvm-svn: 320210
2017-12-09 06:54:44 +08:00
|
|
|
#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA
|
2017-08-22 07:25:50 +08:00
|
|
|
|
|
|
|
#include "FuzzerExtFunctions.h"
|
|
|
|
#include "FuzzerIO.h"
|
|
|
|
#include <cstdarg>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iterator>
|
|
|
|
#include <libgen.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
namespace fuzzer {
|
|
|
|
|
|
|
|
bool IsFile(const std::string &Path) {
|
|
|
|
struct stat St;
|
|
|
|
if (stat(Path.c_str(), &St))
|
|
|
|
return false;
|
|
|
|
return S_ISREG(St.st_mode);
|
|
|
|
}
|
|
|
|
|
2017-11-16 00:45:17 +08:00
|
|
|
static bool IsDirectory(const std::string &Path) {
|
|
|
|
struct stat St;
|
|
|
|
if (stat(Path.c_str(), &St))
|
|
|
|
return false;
|
|
|
|
return S_ISDIR(St.st_mode);
|
|
|
|
}
|
|
|
|
|
2017-08-30 04:51:24 +08:00
|
|
|
size_t FileSize(const std::string &Path) {
|
|
|
|
struct stat St;
|
|
|
|
if (stat(Path.c_str(), &St))
|
|
|
|
return 0;
|
|
|
|
return St.st_size;
|
|
|
|
}
|
|
|
|
|
[libFuzzer] Port to Windows
Summary:
Port libFuzzer to windows-msvc.
This patch allows libFuzzer targets to be built and run on Windows, using -fsanitize=fuzzer and/or fsanitize=fuzzer-no-link. It allows these forms of coverage instrumentation to work on Windows as well.
It does not fix all issues, such as those with -fsanitize-coverage=stack-depth, which is not usable on Windows as of this patch.
It also does not fix any libFuzzer integration tests. Nearly all of them fail to compile, fixing them will come in a later patch, so libFuzzer tests are disabled on Windows until them.
Patch By: metzman
Reviewers: morehouse, rnk
Reviewed By: morehouse, rnk
Subscribers: #sanitizers, delcypher, morehouse, kcc, eraman
Differential Revision: https://reviews.llvm.org/D51022
llvm-svn: 341082
2018-08-30 23:54:44 +08:00
|
|
|
std::string Basename(const std::string &Path) {
|
|
|
|
size_t Pos = Path.rfind(GetSeparator());
|
|
|
|
if (Pos == std::string::npos) return Path;
|
|
|
|
assert(Pos < Path.size());
|
|
|
|
return Path.substr(Pos + 1);
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:25:50 +08:00
|
|
|
void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
|
2017-08-28 07:20:09 +08:00
|
|
|
Vector<std::string> *V, bool TopDir) {
|
2017-08-22 07:25:50 +08:00
|
|
|
auto E = GetEpoch(Dir);
|
|
|
|
if (Epoch)
|
|
|
|
if (E && *Epoch >= E) return;
|
|
|
|
|
|
|
|
DIR *D = opendir(Dir.c_str());
|
|
|
|
if (!D) {
|
2018-04-07 02:15:24 +08:00
|
|
|
Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str());
|
2017-08-22 07:25:50 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
while (auto E = readdir(D)) {
|
|
|
|
std::string Path = DirPlusFile(Dir, E->d_name);
|
2017-11-16 00:45:17 +08:00
|
|
|
if (E->d_type == DT_REG || E->d_type == DT_LNK ||
|
|
|
|
(E->d_type == DT_UNKNOWN && IsFile(Path)))
|
2017-08-22 07:25:50 +08:00
|
|
|
V->push_back(Path);
|
2017-11-16 00:45:17 +08:00
|
|
|
else if ((E->d_type == DT_DIR ||
|
|
|
|
(E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
|
|
|
|
*E->d_name != '.')
|
2017-08-22 07:25:50 +08:00
|
|
|
ListFilesInDirRecursive(Path, Epoch, V, false);
|
|
|
|
}
|
|
|
|
closedir(D);
|
|
|
|
if (Epoch && TopDir)
|
|
|
|
*Epoch = E;
|
|
|
|
}
|
|
|
|
|
2019-02-13 12:04:45 +08:00
|
|
|
|
2019-02-16 05:51:15 +08:00
|
|
|
void IterateDirRecursive(const std::string &Dir,
|
2019-02-13 12:04:45 +08:00
|
|
|
void (*DirPreCallback)(const std::string &Dir),
|
|
|
|
void (*DirPostCallback)(const std::string &Dir),
|
|
|
|
void (*FileCallback)(const std::string &Dir)) {
|
|
|
|
DirPreCallback(Dir);
|
|
|
|
DIR *D = opendir(Dir.c_str());
|
|
|
|
if (!D) return;
|
|
|
|
while (auto E = readdir(D)) {
|
|
|
|
std::string Path = DirPlusFile(Dir, E->d_name);
|
|
|
|
if (E->d_type == DT_REG || E->d_type == DT_LNK ||
|
|
|
|
(E->d_type == DT_UNKNOWN && IsFile(Path)))
|
|
|
|
FileCallback(Path);
|
|
|
|
else if ((E->d_type == DT_DIR ||
|
|
|
|
(E->d_type == DT_UNKNOWN && IsDirectory(Path))) &&
|
|
|
|
*E->d_name != '.')
|
2019-02-16 05:51:15 +08:00
|
|
|
IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
|
2019-02-13 12:04:45 +08:00
|
|
|
}
|
|
|
|
closedir(D);
|
|
|
|
DirPostCallback(Dir);
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:25:50 +08:00
|
|
|
char GetSeparator() {
|
|
|
|
return '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
FILE* OpenFile(int Fd, const char* Mode) {
|
|
|
|
return fdopen(Fd, Mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CloseFile(int fd) {
|
|
|
|
return close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
int DuplicateFile(int Fd) {
|
|
|
|
return dup(Fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveFile(const std::string &Path) {
|
|
|
|
unlink(Path.c_str());
|
|
|
|
}
|
|
|
|
|
2019-04-13 08:20:31 +08:00
|
|
|
void RenameFile(const std::string &OldPath, const std::string &NewPath) {
|
|
|
|
rename(OldPath.c_str(), NewPath.c_str());
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:25:50 +08:00
|
|
|
intptr_t GetHandleFromFd(int fd) {
|
|
|
|
return static_cast<intptr_t>(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string DirName(const std::string &FileName) {
|
|
|
|
char *Tmp = new char[FileName.size() + 1];
|
|
|
|
memcpy(Tmp, FileName.c_str(), FileName.size() + 1);
|
|
|
|
std::string Res = dirname(Tmp);
|
|
|
|
delete [] Tmp;
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string TmpDir() {
|
|
|
|
if (auto Env = getenv("TMPDIR"))
|
|
|
|
return Env;
|
|
|
|
return "/tmp";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInterestingCoverageFile(const std::string &FileName) {
|
|
|
|
if (FileName.find("compiler-rt/lib/") != std::string::npos)
|
|
|
|
return false; // sanitizer internal.
|
|
|
|
if (FileName.find("/usr/lib/") != std::string::npos)
|
|
|
|
return false;
|
|
|
|
if (FileName.find("/usr/include/") != std::string::npos)
|
|
|
|
return false;
|
|
|
|
if (FileName == "<null>")
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RawPrint(const char *Str) {
|
|
|
|
write(2, Str, strlen(Str));
|
|
|
|
}
|
|
|
|
|
2019-02-12 08:12:33 +08:00
|
|
|
void MkDir(const std::string &Path) {
|
|
|
|
mkdir(Path.c_str(), 0700);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RmDir(const std::string &Path) {
|
|
|
|
rmdir(Path.c_str());
|
|
|
|
}
|
|
|
|
|
2019-02-28 03:27:16 +08:00
|
|
|
const std::string &getDevNull() {
|
|
|
|
static const std::string devNull = "/dev/null";
|
|
|
|
return devNull;
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:25:50 +08:00
|
|
|
} // namespace fuzzer
|
|
|
|
|
|
|
|
#endif // LIBFUZZER_POSIX
|