summaryrefslogtreecommitdiff
path: root/libhfcommon
diff options
context:
space:
mode:
authorRobert Swiecki <robert@swiecki.net>2018-01-06 00:42:48 +0100
committerRobert Swiecki <robert@swiecki.net>2018-01-06 00:42:48 +0100
commit79cc04ef167391e49e1d17979148dcc2514d7a23 (patch)
tree591a6c7958c3e03689f88a9bc2c352076cb06ecb /libhfcommon
parent74073e30d2458364e372af5e71a7530641fc7583 (diff)
parent93bf1988b5e5a31ff303f2386411ebe17a35d1da (diff)
downloadhonggfuzz-79cc04ef167391e49e1d17979148dcc2514d7a23.tar.gz
Merge branch 'master' of ssh://github.com/google/honggfuzz
Diffstat (limited to 'libhfcommon')
-rw-r--r--libhfcommon/common.h54
-rw-r--r--libhfcommon/files.c421
-rw-r--r--libhfcommon/files.h67
-rw-r--r--libhfcommon/log.c160
-rw-r--r--libhfcommon/log.h92
-rw-r--r--libhfcommon/ns.c127
-rw-r--r--libhfcommon/ns.h38
-rw-r--r--libhfcommon/util.c647
-rw-r--r--libhfcommon/util.h125
9 files changed, 1731 insertions, 0 deletions
diff --git a/libhfcommon/common.h b/libhfcommon/common.h
new file mode 100644
index 00000000..6423548c
--- /dev/null
+++ b/libhfcommon/common.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * honggfuzz - core macros and helpers
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2010-2017 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#ifndef _HF_COMMON_H_
+#define _HF_COMMON_H_
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef UNUSED
+#define UNUSED __attribute__((unused))
+#endif /* ifndef UNUSED */
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(x) (sizeof(x) / sizeof(*x))
+#endif /* ifndef ARRAYSIZE */
+
+/* Memory barriers */
+#define rmb() __asm__ __volatile__("" ::: "memory")
+#define wmb() __sync_synchronize()
+
+/* TEMP_FAILURE_RETRY, but for all OSes */
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(exp) \
+ ({ \
+ typeof(exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; \
+ })
+#endif /* ifndef TEMP_FAILURE_RETRY */
+
+#endif /* ifndef _HF_COMMON_H_ */
diff --git a/libhfcommon/files.c b/libhfcommon/files.c
new file mode 100644
index 00000000..7dab9920
--- /dev/null
+++ b/libhfcommon/files.c
@@ -0,0 +1,421 @@
+/*
+ *
+ * honggfuzz - file operations
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2010-2015 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#include "libhfcommon/files.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#if defined(_HF_ARCH_LINUX)
+#include <sys/syscall.h>
+#endif /* defined(_HF_ARCH_LINUX) */
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "libhfcommon/common.h"
+#include "libhfcommon/log.h"
+#include "libhfcommon/util.h"
+
+ssize_t files_readFileToBufMax(char* fileName, uint8_t* buf, size_t fileMaxSz) {
+ int fd = open(fileName, O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ PLOG_W("Couldn't open '%s' for R/O", fileName);
+ return -1;
+ }
+
+ ssize_t readSz = files_readFromFd(fd, buf, fileMaxSz);
+ if (readSz < 0) {
+ LOG_W("Couldn't read '%s' to a buf", fileName);
+ }
+ close(fd);
+
+ LOG_D("Read '%zu' bytes from '%s'", readSz, fileName);
+ return readSz;
+}
+
+bool files_writeBufToFile(const char* fileName, const uint8_t* buf, size_t fileSz, int flags) {
+ int fd = open(fileName, flags, 0644);
+ if (fd == -1) {
+ PLOG_W("Couldn't open '%s' for R/W", fileName);
+ return false;
+ }
+
+ bool ret = files_writeToFd(fd, buf, fileSz);
+ if (ret == false) {
+ PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName, fd);
+ unlink(fileName);
+ } else {
+ LOG_D("Written '%zu' bytes to '%s'", fileSz, fileName);
+ }
+
+ close(fd);
+ return ret;
+}
+
+bool files_writeToFd(int fd, const uint8_t* buf, size_t fileSz) {
+ size_t writtenSz = 0;
+ while (writtenSz < fileSz) {
+ ssize_t sz = write(fd, &buf[writtenSz], fileSz - writtenSz);
+ if (sz < 0 && errno == EINTR) continue;
+
+ if (sz < 0) return false;
+
+ writtenSz += sz;
+ }
+ return true;
+}
+
+bool files_writeStrToFd(int fd, const char* str) {
+ return files_writeToFd(fd, (const uint8_t*)str, strlen(str));
+}
+
+ssize_t files_readFromFd(int fd, uint8_t* buf, size_t fileSz) {
+ size_t readSz = 0;
+ while (readSz < fileSz) {
+ ssize_t sz = read(fd, &buf[readSz], fileSz - readSz);
+ if (sz < 0 && errno == EINTR) continue;
+
+ if (sz == 0) break;
+
+ if (sz < 0) return -1;
+
+ readSz += sz;
+ }
+ return (ssize_t)readSz;
+}
+
+bool files_exists(const char* fileName) { return (access(fileName, F_OK) != -1); }
+
+bool files_writePatternToFd(int fd, off_t size, unsigned char p) {
+ void* buf = malloc(size);
+ if (!buf) {
+ PLOG_W("Couldn't allocate memory");
+ return false;
+ }
+
+ memset(buf, p, (size_t)size);
+ int ret = files_writeToFd(fd, buf, size);
+ free(buf);
+
+ return ret;
+}
+
+bool files_sendToSocketNB(int fd, const uint8_t* buf, size_t fileSz) {
+ size_t writtenSz = 0;
+ while (writtenSz < fileSz) {
+ ssize_t sz = send(fd, &buf[writtenSz], fileSz - writtenSz, MSG_DONTWAIT);
+ if (sz < 0 && errno == EINTR) continue;
+
+ if (sz < 0) return false;
+
+ writtenSz += sz;
+ }
+ return true;
+}
+
+bool files_sendToSocket(int fd, const uint8_t* buf, size_t fileSz) {
+ int sendFlags = 0;
+#ifdef _HF_ARCH_DARWIN
+ sendFlags |= SO_NOSIGPIPE;
+#else
+ sendFlags |= MSG_NOSIGNAL;
+#endif
+
+ size_t writtenSz = 0;
+ while (writtenSz < fileSz) {
+ ssize_t sz = send(fd, &buf[writtenSz], fileSz - writtenSz, sendFlags);
+ if (sz < 0 && errno == EINTR) continue;
+
+ if (sz < 0) return false;
+
+ writtenSz += sz;
+ }
+ return true;
+}
+
+const char* files_basename(const char* path) {
+ const char* base = strrchr(path, '/');
+ return base ? base + 1 : path;
+}
+
+/*
+ * dstExists argument can be used by caller for cases where existing destination
+ * file requires special handling (e.g. save unique crashes)
+ */
+bool files_copyFile(const char* source, const char* destination, bool* dstExists, bool try_link) {
+ if (dstExists) {
+ *dstExists = false;
+ }
+
+ if (try_link) {
+ if (link(source, destination) == 0) {
+ return true;
+ } else {
+ if (errno == EEXIST) {
+ // Should kick-in before MAC, so avoid the hassle
+ if (dstExists) *dstExists = true;
+ return false;
+ } else {
+ PLOG_D("Couldn't link '%s' as '%s'", source, destination);
+ /*
+ * Don't fail yet as we might have a running env which doesn't allow
+ * hardlinks (e.g. SELinux)
+ */
+ }
+ }
+ }
+ // Now try with a verbose POSIX alternative
+ int inFD, outFD, dstOpenFlags;
+ mode_t dstFilePerms;
+
+ // O_EXCL is important for saving unique crashes
+ dstOpenFlags = O_CREAT | O_WRONLY | O_CLOEXEC | O_EXCL;
+ dstFilePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+ inFD = open(source, O_RDONLY | O_CLOEXEC);
+ if (inFD == -1) {
+ PLOG_D("Couldn't open '%s' source", source);
+ return false;
+ }
+
+ struct stat inSt;
+ if (fstat(inFD, &inSt) == -1) {
+ PLOG_W("Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
+ close(inFD);
+ return false;
+ }
+
+ outFD = open(destination, dstOpenFlags, dstFilePerms);
+ if (outFD == -1) {
+ if (errno == EEXIST) {
+ if (dstExists) *dstExists = true;
+ }
+ PLOG_D("Couldn't open '%s' destination", destination);
+ close(inFD);
+ return false;
+ }
+
+ uint8_t* inFileBuf = malloc(inSt.st_size);
+ if (!inFileBuf) {
+ PLOG_W("malloc(%zu) failed", (size_t)inSt.st_size);
+ close(inFD);
+ close(outFD);
+ return false;
+ }
+
+ ssize_t readSz = files_readFromFd(inFD, inFileBuf, (size_t)inSt.st_size);
+ if (readSz < 0) {
+ PLOG_W("Couldn't read '%s' to a buf", source);
+ free(inFileBuf);
+ close(inFD);
+ close(outFD);
+ return false;
+ }
+
+ if (files_writeToFd(outFD, inFileBuf, readSz) == false) {
+ PLOG_W("Couldn't write '%zu' bytes to file '%s' (fd='%d')", (size_t)readSz, destination,
+ outFD);
+ unlink(destination);
+ free(inFileBuf);
+ close(inFD);
+ close(outFD);
+ return false;
+ }
+
+ free(inFileBuf);
+ close(inFD);
+ close(outFD);
+ return true;
+}
+
+/*
+ * Reads symbols from src file (one per line) and append them to filterList. The
+ * total number of added symbols is returned.
+ *
+ * Simple wildcard strings are also supported (e.g. mem*)
+ */
+size_t files_parseSymbolFilter(const char* srcFile, char*** filterList) {
+ FILE* f = fopen(srcFile, "rb");
+ if (f == NULL) {
+ PLOG_W("Couldn't open '%s' - R/O mode", srcFile);
+ return 0;
+ }
+
+ char* lineptr = NULL;
+ size_t symbolsRead = 0, n = 0;
+ for (;;) {
+ if (getline(&lineptr, &n, f) == -1) {
+ break;
+ }
+
+ if (strlen(lineptr) < 3) {
+ LOG_F("Input symbol '%s' too short (strlen < 3)", lineptr);
+ symbolsRead = 0;
+ break;
+ }
+ if ((*filterList = (char**)util_Realloc(
+ *filterList, (symbolsRead + 1) * sizeof((*filterList)[0]))) == NULL) {
+ PLOG_W("realloc failed (sz=%zu)", (symbolsRead + 1) * sizeof((*filterList)[0]));
+ symbolsRead = 0;
+ break;
+ }
+ (*filterList)[symbolsRead] = malloc(strlen(lineptr));
+ if (!(*filterList)[symbolsRead]) {
+ PLOG_E("malloc(%zu) failed", strlen(lineptr));
+ symbolsRead = 0;
+ break;
+ }
+ strncpy((*filterList)[symbolsRead], lineptr, strlen(lineptr));
+ symbolsRead++;
+ }
+
+ LOG_I("%zu filter symbols added to list", symbolsRead);
+ fclose(f);
+ free(lineptr);
+ return symbolsRead;
+}
+
+uint8_t* files_mapFile(const char* fileName, off_t* fileSz, int* fd, bool isWritable) {
+ int mmapProt = PROT_READ;
+ if (isWritable) {
+ mmapProt |= PROT_WRITE;
+ }
+
+ if ((*fd = open(fileName, O_RDONLY)) == -1) {
+ PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
+ return NULL;
+ }
+
+ struct stat st;
+ if (fstat(*fd, &st) == -1) {
+ PLOG_W("Couldn't stat() the '%s' file", fileName);
+ close(*fd);
+ return NULL;
+ }
+
+ uint8_t* buf;
+ if ((buf = mmap(NULL, st.st_size, mmapProt, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) {
+ PLOG_W("Couldn't mmap() the '%s' file", fileName);
+ close(*fd);
+ return NULL;
+ }
+
+ *fileSz = st.st_size;
+ return buf;
+}
+
+uint8_t* files_mapFileShared(const char* fileName, off_t* fileSz, int* fd) {
+ if ((*fd = open(fileName, O_RDONLY)) == -1) {
+ PLOG_W("Couldn't open() '%s' file in R/O mode", fileName);
+ return NULL;
+ }
+
+ struct stat st;
+ if (fstat(*fd, &st) == -1) {
+ PLOG_W("Couldn't stat() the '%s' file", fileName);
+ close(*fd);
+ return NULL;
+ }
+
+ uint8_t* buf;
+ if ((buf = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, *fd, 0)) == MAP_FAILED) {
+ PLOG_W("Couldn't mmap() the '%s' file", fileName);
+ close(*fd);
+ return NULL;
+ }
+
+ *fileSz = st.st_size;
+ return buf;
+}
+
+void* files_mapSharedMem(size_t sz, int* fd, const char* dir) {
+ *fd = -1;
+#if defined(_HF_ARCH_LINUX) && defined(__NR_memfd_create)
+#if !defined(MFD_CLOEXEC) /* It's not defined as we didn't include sys/memfd.h, but it's \
+ present with some Linux distros only */
+#define MFD_CLOEXEC 0x0001U
+#endif /* !defined(MFD_CLOEXEC) */
+ *fd = syscall(__NR_memfd_create, "honggfuzz", (uintptr_t)MFD_CLOEXEC);
+#endif /* defined(_HF_ARCH_LINUX) && defined(__NR_memfd_create) */
+ if (*fd == -1) {
+ char template[PATH_MAX];
+ snprintf(template, sizeof(template), "%s/hfuzz.XXXXXX", dir);
+ if ((*fd = mkstemp(template)) == -1) {
+ PLOG_W("mkstemp('%s')", template);
+ return MAP_FAILED;
+ }
+ unlink(template);
+ }
+ if (ftruncate(*fd, sz) == -1) {
+ PLOG_W("ftruncate(%d, %zu)", *fd, sz);
+ close(*fd);
+ *fd = -1;
+ return MAP_FAILED;
+ }
+ void* ret = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
+ if (ret == MAP_FAILED) {
+ PLOG_W("mmap(sz=%zu, fd=%d)", sz, *fd);
+ *fd = -1;
+ close(*fd);
+ return MAP_FAILED;
+ }
+ return ret;
+}
+
+bool files_readPidFromFile(const char* fileName, pid_t* pidPtr) {
+ FILE* fPID = fopen(fileName, "rbe");
+ if (fPID == NULL) {
+ PLOG_W("Couldn't open '%s' - R/O mode", fileName);
+ return false;
+ }
+
+ char* lineptr = NULL;
+ size_t lineSz = 0;
+ ssize_t ret = getline(&lineptr, &lineSz, fPID);
+ fclose(fPID);
+ if (ret == -1) {
+ if (lineSz == 0) {
+ LOG_W("Empty PID file (%s)", fileName);
+ fclose(fPID);
+ free(lineptr);
+ return false;
+ }
+ }
+
+ *pidPtr = atoi(lineptr);
+ free(lineptr);
+ if (*pidPtr < 1) {
+ LOG_W("Invalid PID read from '%s' file", fileName);
+ return false;
+ }
+
+ return true;
+}
diff --git a/libhfcommon/files.h b/libhfcommon/files.h
new file mode 100644
index 00000000..674941fc
--- /dev/null
+++ b/libhfcommon/files.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * honggfuzz - file operations
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2010-2015 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#ifndef _HF_COMMON_FILES_H_
+#define _HF_COMMON_FILES_H_
+
+#include "common.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+
+extern ssize_t files_readFileToBufMax(char* fileName, uint8_t* buf, size_t fileMaxSz);
+
+extern bool files_writeBufToFile(
+ const char* fileName, const uint8_t* buf, size_t fileSz, int flags);
+
+extern bool files_writeToFd(int fd, const uint8_t* buf, size_t fileSz);
+
+extern bool files_writeStrToFd(int fd, const char* str);
+
+extern ssize_t files_readFromFd(int fd, uint8_t* buf, size_t fileSz);
+
+extern bool files_writePatternToFd(int fd, off_t size, unsigned char p);
+
+bool files_sendToSocketNB(int fd, const uint8_t* buf, size_t fileSz);
+
+bool files_sendToSocket(int fd, const uint8_t* buf, size_t fileSz);
+
+extern bool files_exists(const char* fileName);
+
+extern const char* files_basename(const char* path);
+
+extern bool files_copyFile(
+ const char* source, const char* destination, bool* dstExists, bool try_link);
+
+extern uint8_t* files_mapFile(const char* fileName, off_t* fileSz, int* fd, bool isWritable);
+
+extern uint8_t* files_mapFileShared(const char* fileName, off_t* fileSz, int* fd);
+
+extern void* files_mapSharedMem(size_t sz, int* fd, const char* dir);
+
+extern bool files_readPidFromFile(const char* fileName, pid_t* pidPtr);
+
+extern size_t files_parseSymbolFilter(const char* inFIle, char*** filterList);
+
+#endif /* ifndef HF_COMMON_FILES */
diff --git a/libhfcommon/log.c b/libhfcommon/log.c
new file mode 100644
index 00000000..2e627728
--- /dev/null
+++ b/libhfcommon/log.c
@@ -0,0 +1,160 @@
+/*
+
+ nsjail - logging
+ -----------------------------------------
+
+ Copyright 2014 Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+#include "libhfcommon/log.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "libhfcommon/common.h"
+#include "libhfcommon/util.h"
+
+#if defined(_HF_ARCH_LINUX)
+#include <sys/syscall.h>
+#define __hf_pid() (pid_t) syscall(__NR_gettid)
+#else /* defined(_HF_ARCH_LINUX) */
+#define __hf_pid() getpid()
+#endif /* defined(_HF_ARCH_LINUX) */
+
+static int log_fd = STDERR_FILENO;
+static bool log_fd_isatty = false;
+enum llevel_t log_level = INFO;
+static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+__attribute__((constructor)) static void log_init(void) {
+ log_level = INFO;
+ log_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 0);
+ if (log_fd == -1) {
+ log_fd = STDERR_FILENO;
+ }
+ log_fd_isatty = isatty(log_fd);
+}
+
+/*
+ * Log to stderr by default. Use a dup()d fd, because in the future we'll associate the
+ * connection socket with fd (0, 1, 2).
+ */
+bool logInitLogFile(const char* logfile, enum llevel_t ll) {
+ log_level = ll;
+
+ if (logfile == NULL) {
+ return true;
+ }
+
+ log_fd = open(logfile, O_CREAT | O_RDWR | O_TRUNC, 0640);
+ if (log_fd == -1) {
+ log_fd = STDERR_FILENO;
+ PLOG_E("Couldn't open logfile open('%s')", logfile);
+ return false;
+ }
+ log_fd_isatty = (isatty(log_fd) == 1 ? true : false);
+ return true;
+}
+
+void logLog(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...) {
+ char strerr[512];
+ if (perr == true) {
+ snprintf(strerr, sizeof(strerr), "%s", strerror(errno));
+ }
+ struct ll_t {
+ const char* descr;
+ const char* prefix;
+ const bool print_funcline;
+ const bool print_time;
+ };
+ static const struct ll_t logLevels[] = {
+ {"F", "\033[7;35m", true, true},
+ {"E", "\033[1;31m", true, true},
+ {"W", "\033[0;33m", true, true},
+ {"I", "\033[1m", false, false},
+ {"D", "\033[0;4m", true, true},
+ {"HR", "\033[0m", false, false},
+ {"HB", "\033[1m", false, false},
+ };
+
+ time_t ltstamp = time(NULL);
+ struct tm utctime;
+ localtime_r(&ltstamp, &utctime);
+ char timestr[32];
+ if (strftime(timestr, sizeof(timestr) - 1, "%FT%T%z", &utctime) == 0) {
+ timestr[0] = '\0';
+ }
+
+ /* Start printing logs */
+ {
+ MX_LOCK(&log_mutex);
+
+ if (log_fd_isatty) {
+ dprintf(log_fd, "%s", logLevels[ll].prefix);
+ }
+ if (logLevels[ll].print_time) {
+ dprintf(log_fd, "[%s][%s][%d] ", timestr, logLevels[ll].descr, __hf_pid());
+ }
+ if (logLevels[ll].print_funcline) {
+ dprintf(log_fd, "%s():%d ", fn, ln);
+ }
+
+ va_list args;
+ va_start(args, fmt);
+ vdprintf(log_fd, fmt, args);
+ va_end(args);
+
+ if (perr == true) {
+ dprintf(log_fd, ": %s", strerr);
+ }
+ if (log_fd_isatty) {
+ dprintf(log_fd, "\033[0m");
+ }
+ dprintf(log_fd, "\n");
+
+ MX_UNLOCK(&log_mutex);
+ }
+ /* End printing logs */
+
+ if (ll == FATAL) {
+ exit(1);
+ }
+}
+
+void logStop(int sig) { LOG_I("Server stops due to fatal signal (%d) caught. Exiting", sig); }
+
+void logRedirectLogFD(int fd) { log_fd = fd; }
+
+void logDirectlyToFD(const char* msg) { dprintf(log_fd, "%s", msg); }
+
+pthread_mutex_t* logMutexGet(void) { return &log_mutex; }
+
+void logMutexReset(void) { pthread_mutex_init(&log_mutex, NULL); }
+
+bool logIsTTY(void) { return log_fd_isatty; }
+
+int logFd(void) { return log_fd; }
diff --git a/libhfcommon/log.h b/libhfcommon/log.h
new file mode 100644
index 00000000..a6c8706d
--- /dev/null
+++ b/libhfcommon/log.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * honggfuzz - logging
+ * -----------------------------------------
+ *
+ * Copyright 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _HF_COMMON_LOG_H_
+#define _HF_COMMON_LOG_H_
+
+#include <pthread.h>
+#include <stdbool.h>
+
+enum llevel_t { FATAL = 0, ERROR, WARNING, INFO, DEBUG, HELP, HELP_BOLD };
+
+extern enum llevel_t log_level;
+
+#define LOG_HELP(...) logLog(HELP, __FUNCTION__, __LINE__, false, __VA_ARGS__);
+#define LOG_HELP_BOLD(...) logLog(HELP_BOLD, __FUNCTION__, __LINE__, false, __VA_ARGS__);
+
+#define LOG_D(...) \
+ if (log_level >= DEBUG) { \
+ logLog(DEBUG, __FUNCTION__, __LINE__, false, __VA_ARGS__); \
+ }
+#define LOG_I(...) \
+ if (log_level >= INFO) { \
+ logLog(INFO, __FUNCTION__, __LINE__, false, __VA_ARGS__); \
+ }
+#define LOG_W(...) \
+ if (log_level >= WARNING) { \
+ logLog(WARNING, __FUNCTION__, __LINE__, false, __VA_ARGS__); \
+ }
+#define LOG_E(...) \
+ if (log_level >= ERROR) { \
+ logLog(ERROR, __FUNCTION__, __LINE__, false, __VA_ARGS__); \
+ }
+#define LOG_F(...) \
+ if (log_level >= FATAL) { \
+ logLog(FATAL, __FUNCTION__, __LINE__, false, __VA_ARGS__); \
+ }
+
+#define PLOG_D(...) \
+ if (log_level >= DEBUG) { \
+ logLog(DEBUG, __FUNCTION__, __LINE__, true, __VA_ARGS__); \
+ }
+#define PLOG_I(...) \
+ if (log_level >= INFO) { \
+ logLog(INFO, __FUNCTION__, __LINE__, true, __VA_ARGS__); \
+ }
+#define PLOG_W(...) \
+ if (log_level >= WARNING) { \
+ logLog(WARNING, __FUNCTION__, __LINE__, true, __VA_ARGS__); \
+ }
+#define PLOG_E(...) \
+ if (log_level >= ERROR) { \
+ logLog(ERROR, __FUNCTION__, __LINE__, true, __VA_ARGS__); \
+ }
+#define PLOG_F(...) \
+ if (log_level >= FATAL) { \
+ logLog(FATAL, __FUNCTION__, __LINE__, true, __VA_ARGS__); \
+ }
+
+extern bool logInitLogFile(const char* logfile, enum llevel_t ll);
+
+extern void logLog(enum llevel_t ll, const char* fn, int ln, bool perr, const char* fmt, ...)
+ __attribute__((format(printf, 5, 6)));
+
+extern void logStop(int sig);
+
+extern bool logIsTTY(void);
+
+extern int logFd(void);
+
+extern pthread_mutex_t* logMutexGet(void);
+
+void logMutexReset(void);
+
+#endif /* ifndef _HF_COMMON_LOG_H_ */
diff --git a/libhfcommon/ns.c b/libhfcommon/ns.c
new file mode 100644
index 00000000..25c25f90
--- /dev/null
+++ b/libhfcommon/ns.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * honggfuzz - namespace-related utilities
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2017 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#include "libhfcommon/ns.h"
+
+#include "libhfcommon/common.h"
+#include "libhfcommon/files.h"
+#include "libhfcommon/log.h"
+
+#if defined(_HF_ARCH_LINUX)
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+bool nsEnter(uintptr_t cloneFlags) {
+ pid_t current_uid = getuid();
+ gid_t current_gid = getgid();
+
+ if (unshare(cloneFlags) == -1) {
+ PLOG_E("unshare(0x%tx)", cloneFlags);
+ return false;
+ }
+
+ const char* deny_str = "deny";
+ if (files_writeBufToFile("/proc/self/setgroups", (const uint8_t*)deny_str, strlen(deny_str),
+ O_WRONLY) == false) {
+ PLOG_E("Couldn't write to /proc/self/setgroups");
+ return false;
+ }
+
+ char gid_map[4096];
+ snprintf(gid_map, sizeof(gid_map), "%d %d 1", (int)current_gid, (int)current_gid);
+ if (files_writeBufToFile(
+ "/proc/self/gid_map", (const uint8_t*)gid_map, strlen(gid_map), O_WRONLY) == false) {
+ PLOG_E("Couldn't write to /proc/self/gid_map");
+ return false;
+ }
+
+ char uid_map[4096];
+ snprintf(uid_map, sizeof(uid_map), "%d %d 1", (int)current_uid, (int)current_uid);
+ if (files_writeBufToFile(
+ "/proc/self/uid_map", (const uint8_t*)uid_map, strlen(uid_map), O_WRONLY) == false) {
+ PLOG_E("Couldn't write to /proc/self/uid_map");
+ return false;
+ }
+
+ if (setresgid(current_gid, current_gid, current_gid) == -1) {
+ PLOG_E("setresgid(%d)", (int)current_gid);
+ return false;
+ }
+ if (setresuid(current_uid, current_uid, current_uid) == -1) {
+ PLOG_E("setresuid(%d)", (int)current_uid);
+ return false;
+ }
+
+ return true;
+}
+
+bool nsIfaceUp(const char* ifacename) {
+ int sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
+ if (sock == -1) {
+ PLOG_E("socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP)");
+ return false;
+ }
+
+ struct ifreq ifr;
+ memset(&ifr, '\0', sizeof(ifr));
+ snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename);
+
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
+ PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
+ close(sock);
+ return false;
+ }
+
+ ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
+
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
+ PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
+ close(sock);
+ return false;
+ }
+
+ close(sock);
+ return true;
+}
+
+bool nsMountTmpfs(const char* dst) {
+ if (mount(NULL, dst, "tmpfs", 0, NULL) == -1) {
+ PLOG_E("mount(dst='%s', tmpfs)", dst);
+ return false;
+ }
+ return true;
+}
+
+#endif /* defined(_HF_ARCH_LINUX) */
diff --git a/libhfcommon/ns.h b/libhfcommon/ns.h
new file mode 100644
index 00000000..882f7547
--- /dev/null
+++ b/libhfcommon/ns.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * honggfuzz - namespace related utils
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2017 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#ifndef _HF_NS_H_
+#define _HF_NS_H_
+
+#if defined(_HF_ARCH_LINUX)
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+bool nsEnter(uintptr_t cloneFlags);
+bool nsIfaceUp(const char* ifacename);
+bool nsMountTmpfs(const char* dst);
+
+#endif /* defined(_HF_ARCH_LINUX) */
+
+#endif
diff --git a/libhfcommon/util.c b/libhfcommon/util.c
new file mode 100644
index 00000000..5745a4b2
--- /dev/null
+++ b/libhfcommon/util.c
@@ -0,0 +1,647 @@
+/*
+ *
+ * honggfuzz - utilities
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2010-2015 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#include "libhfcommon/util.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <math.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "libhfcommon/common.h"
+#include "libhfcommon/files.h"
+#include "libhfcommon/log.h"
+
+void* util_Malloc(size_t sz) {
+ void* p = malloc(sz);
+ if (p == NULL) {
+ LOG_F("malloc(size='%zu')", sz);
+ }
+ return p;
+}
+
+void* util_Calloc(size_t sz) {
+ void* p = util_Malloc(sz);
+ memset(p, '\0', sz);
+ return p;
+}
+
+extern void* util_Realloc(void* ptr, size_t sz) {
+ void* ret = realloc(ptr, sz);
+ if (ret == NULL) {
+ PLOG_W("realloc(%p, %zu)", ptr, sz);
+ free(ptr);
+ return NULL;
+ }
+ return ret;
+}
+
+void* util_MMap(size_t sz) {
+ void* p = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (p == MAP_FAILED) {
+ LOG_F("mmap(size='%zu')", sz);
+ }
+ return p;
+}
+
+char* util_StrDup(const char* s) {
+ char* ret = strdup(s);
+ if (ret == NULL) {
+ LOG_F("strdup(size=%zu)", strlen(s));
+ }
+ return ret;
+}
+
+static __thread pthread_once_t rndThreadOnce = PTHREAD_ONCE_INIT;
+static __thread uint64_t rndState[2];
+
+static void util_rndInitThread(void) {
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ PLOG_F("Couldn't open /dev/urandom for reading");
+ }
+ if (files_readFromFd(fd, (uint8_t*)rndState, sizeof(rndState)) != sizeof(rndState)) {
+ PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndState));
+ }
+ close(fd);
+}
+
+/*
+ * xoroshiro128plus by David Blackman and Sebastiano Vigna
+ */
+static inline uint64_t util_RotL(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); }
+
+static inline uint64_t util_InternalRnd64(void) {
+ const uint64_t s0 = rndState[0];
+ uint64_t s1 = rndState[1];
+ const uint64_t result = s0 + s1;
+ s1 ^= s0;
+ rndState[0] = util_RotL(s0, 55) ^ s1 ^ (s1 << 14);
+ rndState[1] = util_RotL(s1, 36);
+
+ return result;
+}
+
+uint64_t util_rnd64(void) {
+ pthread_once(&rndThreadOnce, util_rndInitThread);
+ return util_InternalRnd64();
+}
+
+uint64_t util_rndGet(uint64_t min, uint64_t max) {
+ if (min > max) {
+ LOG_F("min:%" PRIu64 " > max:%" PRIu64, min, max);
+ }
+
+ if (max == UINT64_MAX) {
+ return util_rnd64();
+ }
+
+ return ((util_rnd64() % (max - min + 1)) + min);
+}
+
+void util_rndBuf(uint8_t* buf, size_t sz) {
+ pthread_once(&rndThreadOnce, util_rndInitThread);
+ if (sz == 0) {
+ return;
+ }
+ for (size_t i = 0; i < sz; i++) {
+ buf[i] = (uint8_t)util_InternalRnd64();
+ }
+}
+
+/*
+ * Function has variable length stack size, although already we know it's invoked
+ * with relatively small sizes (max is _HF_REPORT_SIZE), thus safe to silent warning.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+int util_vssnprintf(char* str, size_t size, const char* format, va_list ap) {
+ char buf1[size];
+ char buf2[size];
+
+ strncpy(buf1, str, size);
+
+ vsnprintf(buf2, size, format, ap);
+
+ return snprintf(str, size, "%s%s", buf1, buf2);
+}
+
+int util_ssnprintf(char* str, size_t size, const char* format, ...) {
+ char buf1[size];
+ char buf2[size];
+
+ snprintf(buf1, sizeof(buf1), "%s", str);
+
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buf2, size, format, args);
+ va_end(args);
+
+ return snprintf(str, size, "%s%s", buf1, buf2);
+}
+
+#pragma GCC diagnostic pop /* EOF diagnostic ignored "-Wstack-usage=" */
+
+void util_getLocalTime(const char* fmt, char* buf, size_t len, time_t tm) {
+ struct tm ltime;
+ localtime_r(&tm, &ltime);
+ if (strftime(buf, len, fmt, &ltime) < 1) {
+ snprintf(buf, len, "[date fetch error]");
+ }
+}
+
+void util_nullifyStdio(void) {
+ int fd = open("/dev/null", O_RDWR);
+
+ if (fd == -1) {
+ PLOG_E("Couldn't open '/dev/null'");
+ return;
+ }
+
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+
+ if (fd > 2) {
+ close(fd);
+ }
+}
+
+bool util_redirectStdin(const char* inputFile) {
+ int fd = open(inputFile, O_RDONLY);
+
+ if (fd == -1) {
+ PLOG_W("Couldn't open '%s'", inputFile);
+ return false;
+ }
+
+ dup2(fd, 0);
+ if (fd != 0) {
+ close(fd);
+ }
+
+ return true;
+}
+
+/*
+ * This is not a cryptographically secure hash
+ */
+uint64_t util_hash(const char* buf, size_t len) {
+ uint64_t ret = 0;
+
+ for (size_t i = 0; i < len; i++) {
+ ret += buf[i];
+ ret += (ret << 10);
+ ret ^= (ret >> 6);
+ }
+
+ return ret;
+}
+
+int64_t util_timeNowMillis(void) {
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) == -1) {
+ PLOG_F("gettimeofday()");
+ }
+
+ return (((int64_t)tv.tv_sec * 1000LL) + ((int64_t)tv.tv_usec / 1000LL));
+}
+
+uint64_t util_getUINT32(const uint8_t* buf) {
+ uint32_t r;
+ memcpy(&r, buf, sizeof(r));
+ return (uint64_t)r;
+}
+
+uint64_t util_getUINT64(const uint8_t* buf) {
+ uint64_t r;
+ memcpy(&r, buf, sizeof(r));
+ return r;
+}
+
+void util_mutexLock(pthread_mutex_t* mutex, const char* func, int line) {
+ if (pthread_mutex_lock(mutex)) {
+ PLOG_F("%s():%d pthread_mutex_lock(%p)", func, line, (void*)mutex);
+ }
+}
+
+void util_mutexUnlock(pthread_mutex_t* mutex, const char* func, int line) {
+ if (pthread_mutex_unlock(mutex)) {
+ PLOG_F("%s():%d pthread_mutex_unlock(%p)", func, line, (void*)mutex);
+ }
+}
+
+void util_mutexRWLockRead(pthread_rwlock_t* mutex, const char* func, int line) {
+ if (pthread_rwlock_rdlock(mutex)) {
+ PLOG_F("%s():%d pthread_rwlock_rdlock(%p)", func, line, (void*)mutex);
+ }
+}
+
+void util_mutexRWLockWrite(pthread_rwlock_t* mutex, const char* func, int line) {
+ if (pthread_rwlock_wrlock(mutex)) {
+ PLOG_F("%s():%d pthread_rwlock_wrlock(%p)", func, line, (void*)mutex);
+ }
+}
+
+void util_mutexRWUnlock(pthread_rwlock_t* mutex, const char* func, int line) {
+ if (pthread_rwlock_unlock(mutex)) {
+ PLOG_F("%s():%d pthread_rwlock_unlock(%p)", func, line, (void*)mutex);
+ }
+}
+
+int64_t fastArray64Search(uint64_t* array, size_t arraySz, uint64_t key) {
+ size_t low = 0;
+ size_t high = arraySz - 1;
+ size_t mid;
+
+ while (array[high] != array[low] && key >= array[low] && key <= array[high]) {
+ mid = low + (key - array[low]) * ((high - low) / (array[high] - array[low]));
+
+ if (array[mid] < key) {
+ low = mid + 1;
+ } else if (key < array[mid]) {
+ high = mid - 1;
+ } else {
+ return mid;
+ }
+ }
+
+ if (key == array[low]) {
+ return low;
+ } else {
+ return -1;
+ }
+}
+
+bool util_isANumber(const char* s) {
+ if (!isdigit(s[0])) {
+ return false;
+ }
+ for (int i = 0; s[i]; s++) {
+ if (!isdigit(s[i]) && s[i] != 'x') {
+ return false;
+ }
+ }
+ return true;
+}
+
+size_t util_decodeCString(char* s) {
+ size_t len = strlen(s);
+ size_t o = 0;
+ for (size_t i = 0; s[i] != '\0' && s[i] != '"' && i < len; i++, o++) {
+ switch (s[i]) {
+ case '\\': {
+ i++;
+ if (i >= len) {
+ continue;
+ }
+ switch (s[i]) {
+ case 'a':
+ s[o] = '\a';
+ break;
+ case 'r':
+ s[o] = '\r';
+ break;
+ case 'n':
+ s[o] = '\n';
+ break;
+ case 't':
+ s[o] = '\t';
+ break;
+ case '0':
+ s[o] = '\0';
+ break;
+ case 'x': {
+ /* Yup, this can overflow */
+ char hex[] = {s[i + 1], s[i + 2], 0};
+ s[o] = strtoul(hex, NULL, 16);
+ i += 2;
+ break;
+ }
+ default:
+ s[o] = s[i];
+ break;
+ }
+ break;
+ }
+ default: {
+ s[o] = s[i];
+ break;
+ }
+ }
+ }
+ s[o] = '\0';
+ return o;
+}
+
+/* ISO 3309 CRC-64 Poly table */
+static const uint64_t util_CRC64ISOPoly[] = {
+ 0x0000000000000000ULL,
+ 0x01B0000000000000ULL,
+ 0x0360000000000000ULL,
+ 0x02D0000000000000ULL,
+ 0x06C0000000000000ULL,
+ 0x0770000000000000ULL,
+ 0x05A0000000000000ULL,
+ 0x0410000000000000ULL,
+ 0x0D80000000000000ULL,
+ 0x0C30000000000000ULL,
+ 0x0EE0000000000000ULL,
+ 0x0F50000000000000ULL,
+ 0x0B40000000000000ULL,
+ 0x0AF0000000000000ULL,
+ 0x0820000000000000ULL,
+ 0x0990000000000000ULL,
+ 0x1B00000000000000ULL,
+ 0x1AB0000000000000ULL,
+ 0x1860000000000000ULL,
+ 0x19D0000000000000ULL,
+ 0x1DC0000000000000ULL,
+ 0x1C70000000000000ULL,
+ 0x1EA0000000000000ULL,
+ 0x1F10000000000000ULL,
+ 0x1680000000000000ULL,
+ 0x1730000000000000ULL,
+ 0x15E0000000000000ULL,
+ 0x1450000000000000ULL,
+ 0x1040000000000000ULL,
+ 0x11F0000000000000ULL,
+ 0x1320000000000000ULL,
+ 0x1290000000000000ULL,
+ 0x3600000000000000ULL,
+ 0x37B0000000000000ULL,
+ 0x3560000000000000ULL,
+ 0x34D0000000000000ULL,
+ 0x30C0000000000000ULL,
+ 0x3170000000000000ULL,
+ 0x33A0000000000000ULL,
+ 0x3210000000000000ULL,
+ 0x3B80000000000000ULL,
+ 0x3A30000000000000ULL,
+ 0x38E0000000000000ULL,
+ 0x3950000000000000ULL,
+ 0x3D40000000000000ULL,
+ 0x3CF0000000000000ULL,
+ 0x3E20000000000000ULL,
+ 0x3F90000000000000ULL,
+ 0x2D00000000000000ULL,
+ 0x2CB0000000000000ULL,
+ 0x2E60000000000000ULL,
+ 0x2FD0000000000000ULL,
+ 0x2BC0000000000000ULL,
+ 0x2A70000000000000ULL,
+ 0x28A0000000000000ULL,
+ 0x2910000000000000ULL,
+ 0x2080000000000000ULL,
+ 0x2130000000000000ULL,
+ 0x23E0000000000000ULL,
+ 0x2250000000000000ULL,
+ 0x2640000000000000ULL,
+ 0x27F0000000000000ULL,
+ 0x2520000000000000ULL,
+ 0x2490000000000000ULL,
+ 0x6C00000000000000ULL,
+ 0x6DB0000000000000ULL,
+ 0x6F60000000000000ULL,
+ 0x6ED0000000000000ULL,
+ 0x6AC0000000000000ULL,
+ 0x6B70000000000000ULL,
+ 0x69A0000000000000ULL,
+ 0x6810000000000000ULL,
+ 0x6180000000000000ULL,
+ 0x6030000000000000ULL,
+ 0x62E0000000000000ULL,
+ 0x6350000000000000ULL,
+ 0x6740000000000000ULL,
+ 0x66F0000000000000ULL,
+ 0x6420000000000000ULL,
+ 0x6590000000000000ULL,
+ 0x7700000000000000ULL,
+ 0x76B0000000000000ULL,
+ 0x7460000000000000ULL,
+ 0x75D0000000000000ULL,
+ 0x71C0000000000000ULL,
+ 0x7070000000000000ULL,
+ 0x72A0000000000000ULL,
+ 0x7310000000000000ULL,
+ 0x7A80000000000000ULL,
+ 0x7B30000000000000ULL,
+ 0x79E0000000000000ULL,
+ 0x7850000000000000ULL,
+ 0x7C40000000000000ULL,
+ 0x7DF0000000000000ULL,
+ 0x7F20000000000000ULL,
+ 0x7E90000000000000ULL,
+ 0x5A00000000000000ULL,
+ 0x5BB0000000000000ULL,
+ 0x5960000000000000ULL,
+ 0x58D0000000000000ULL,
+ 0x5CC0000000000000ULL,
+ 0x5D70000000000000ULL,
+ 0x5FA0000000000000ULL,
+ 0x5E10000000000000ULL,
+ 0x5780000000000000ULL,
+ 0x5630000000000000ULL,
+ 0x54E0000000000000ULL,
+ 0x5550000000000000ULL,
+ 0x5140000000000000ULL,
+ 0x50F0000000000000ULL,
+ 0x5220000000000000ULL,
+ 0x5390000000000000ULL,
+ 0x4100000000000000ULL,
+ 0x40B0000000000000ULL,
+ 0x4260000000000000ULL,
+ 0x43D0000000000000ULL,
+ 0x47C0000000000000ULL,
+ 0x4670000000000000ULL,
+ 0x44A0000000000000ULL,
+ 0x4510000000000000ULL,
+ 0x4C80000000000000ULL,
+ 0x4D30000000000000ULL,
+ 0x4FE0000000000000ULL,
+ 0x4E50000000000000ULL,
+ 0x4A40000000000000ULL,
+ 0x4BF0000000000000ULL,
+ 0x4920000000000000ULL,
+ 0x4890000000000000ULL,
+ 0xD800000000000000ULL,
+ 0xD9B0000000000000ULL,
+ 0xDB60000000000000ULL,
+ 0xDAD0000000000000ULL,
+ 0xDEC0000000000000ULL,
+ 0xDF70000000000000ULL,
+ 0xDDA0000000000000ULL,
+ 0xDC10000000000000ULL,
+ 0xD580000000000000ULL,
+ 0xD430000000000000ULL,
+ 0xD6E0000000000000ULL,
+ 0xD750000000000000ULL,
+ 0xD340000000000000ULL,
+ 0xD2F0000000000000ULL,
+ 0xD020000000000000ULL,
+ 0xD190000000000000ULL,
+ 0xC300000000000000ULL,
+ 0xC2B0000000000000ULL,
+ 0xC060000000000000ULL,
+ 0xC1D0000000000000ULL,
+ 0xC5C0000000000000ULL,
+ 0xC470000000000000ULL,
+ 0xC6A0000000000000ULL,
+ 0xC710000000000000ULL,
+ 0xCE80000000000000ULL,
+ 0xCF30000000000000ULL,
+ 0xCDE0000000000000ULL,
+ 0xCC50000000000000ULL,
+ 0xC840000000000000ULL,
+ 0xC9F0000000000000ULL,
+ 0xCB20000000000000ULL,
+ 0xCA90000000000000ULL,
+ 0xEE00000000000000ULL,
+ 0xEFB0000000000000ULL,
+ 0xED60000000000000ULL,
+ 0xECD0000000000000ULL,
+ 0xE8C0000000000000ULL,
+ 0xE970000000000000ULL,
+ 0xEBA0000000000000ULL,
+ 0xEA10000000000000ULL,
+ 0xE380000000000000ULL,
+ 0xE230000000000000ULL,
+ 0xE0E0000000000000ULL,
+ 0xE150000000000000ULL,
+ 0xE540000000000000ULL,
+ 0xE4F0000000000000ULL,
+ 0xE620000000000000ULL,
+ 0xE790000000000000ULL,
+ 0xF500000000000000ULL,
+ 0xF4B0000000000000ULL,
+ 0xF660000000000000ULL,
+ 0xF7D0000000000000ULL,
+ 0xF3C0000000000000ULL,
+ 0xF270000000000000ULL,
+ 0xF0A0000000000000ULL,
+ 0xF110000000000000ULL,
+ 0xF880000000000000ULL,
+ 0xF930000000000000ULL,
+ 0xFBE0000000000000ULL,
+ 0xFA50000000000000ULL,
+ 0xFE40000000000000ULL,
+ 0xFFF0000000000000ULL,
+ 0xFD20000000000000ULL,
+ 0xFC90000000000000ULL,
+ 0xB400000000000000ULL,
+ 0xB5B0000000000000ULL,
+ 0xB760000000000000ULL,
+ 0xB6D0000000000000ULL,
+ 0xB2C0000000000000ULL,
+ 0xB370000000000000ULL,
+ 0xB1A0000000000000ULL,
+ 0xB010000000000000ULL,
+ 0xB980000000000000ULL,
+ 0xB830000000000000ULL,
+ 0xBAE0000000000000ULL,
+ 0xBB50000000000000ULL,
+ 0xBF40000000000000ULL,
+ 0xBEF0000000000000ULL,
+ 0xBC20000000000000ULL,
+ 0xBD90000000000000ULL,
+ 0xAF00000000000000ULL,
+ 0xAEB0000000000000ULL,
+ 0xAC60000000000000ULL,
+ 0xADD0000000000000ULL,
+ 0xA9C0000000000000ULL,
+ 0xA870000000000000ULL,
+ 0xAAA0000000000000ULL,
+ 0xAB10000000000000ULL,
+ 0xA280000000000000ULL,
+ 0xA330000000000000ULL,
+ 0xA1E0000000000000ULL,
+ 0xA050000000000000ULL,
+ 0xA440000000000000ULL,
+ 0xA5F0000000000000ULL,
+ 0xA720000000000000ULL,
+ 0xA690000000000000ULL,
+ 0x8200000000000000ULL,
+ 0x83B0000000000000ULL,
+ 0x8160000000000000ULL,
+ 0x80D0000000000000ULL,
+ 0x84C0000000000000ULL,
+ 0x8570000000000000ULL,
+ 0x87A0000000000000ULL,
+ 0x8610000000000000ULL,
+ 0x8F80000000000000ULL,
+ 0x8E30000000000000ULL,
+ 0x8CE0000000000000ULL,
+ 0x8D50000000000000ULL,
+ 0x8940000000000000ULL,
+ 0x88F0000000000000ULL,
+ 0x8A20000000000000ULL,
+ 0x8B90000000000000ULL,
+ 0x9900000000000000ULL,
+ 0x98B0000000000000ULL,
+ 0x9A60000000000000ULL,
+ 0x9BD0000000000000ULL,
+ 0x9FC0000000000000ULL,
+ 0x9E70000000000000ULL,
+ 0x9CA0000000000000ULL,
+ 0x9D10000000000000ULL,
+ 0x9480000000000000ULL,
+ 0x9530000000000000ULL,
+ 0x97E0000000000000ULL,
+ 0x9650000000000000ULL,
+ 0x9240000000000000ULL,
+ 0x93F0000000000000ULL,
+ 0x9120000000000000ULL,
+ 0x9090000000000000ULL,
+};
+
+uint64_t util_CRC64(const uint8_t* buf, size_t len) {
+ uint64_t res = 0ULL;
+
+ for (size_t i = 0; i < len; i++) {
+ res = util_CRC64ISOPoly[(uint8_t)res ^ buf[i]] ^ (res >> 8);
+ }
+
+ return res;
+}
+
+uint64_t util_CRC64Rev(const uint8_t* buf, size_t len) {
+ uint64_t res = 0ULL;
+
+ for (ssize_t i = (ssize_t)len - 1; i >= 0; i--) {
+ res = util_CRC64ISOPoly[(uint8_t)res ^ buf[i]] ^ (res >> 8);
+ }
+
+ return res;
+}
diff --git a/libhfcommon/util.h b/libhfcommon/util.h
new file mode 100644
index 00000000..26fe6e66
--- /dev/null
+++ b/libhfcommon/util.h
@@ -0,0 +1,125 @@
+/*
+ *
+ * honggfuzz - utilities
+ * -----------------------------------------
+ *
+ * Author: Robert Swiecki <swiecki@google.com>
+ *
+ * Copyright 2010-2015 by Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ *
+ */
+
+#ifndef _HF_COMMON_UTIL_H_
+#define _HF_COMMON_UTIL_H_
+
+#include <pthread.h>
+#include <stdarg.h>
+#ifdef __clang__
+#include <stdatomic.h>
+#endif
+#include <stdbool.h>
+#include <stdint.h>
+#include <time.h>
+
+#define MX_LOCK(m) util_mutexLock(m, __func__, __LINE__)
+#define MX_UNLOCK(m) util_mutexUnlock(m, __func__, __LINE__)
+#define MX_RWLOCK_READ(m) util_mutexRWLockRead(m, __func__, __LINE__)
+#define MX_RWLOCK_WRITE(m) util_mutexRWLockWrite(m, __func__, __LINE__)
+#define MX_RWLOCK_UNLOCK(m) util_mutexRWUnlock(m, __func__, __LINE__)
+
+/* Atomics */
+#define ATOMIC_GET(x) __atomic_load_n(&(x), __ATOMIC_SEQ_CST)
+#define ATOMIC_SET(x, y) __atomic_store_n(&(x), y, __ATOMIC_SEQ_CST)
+#define ATOMIC_CLEAR(x) __atomic_store_n(&(x), 0, __ATOMIC_SEQ_CST)
+#define ATOMIC_XCHG(x, y) __atomic_exchange_n(&(x), y, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_INC(x) __atomic_add_fetch(&(x), 1, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_INC(x) __atomic_fetch_add(&(x), 1, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_DEC(x) __atomic_sub_fetch(&(x), 1, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_DEC(x) __atomic_fetch_sub(&(x), 1, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_ADD(x, y) __atomic_add_fetch(&(x), y, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_ADD(x, y) __atomic_fetch_add(&(x), y, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_SUB(x, y) __atomic_sub_fetch(&(x), y, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_SUB(x, y) __atomic_fetch_sub(&(x), y, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_AND(x, y) __atomic_and_fetch(&(x), y, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_AND(x, y) __atomic_fetch_and(&(x), y, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_OR(x, y) __atomic_or_fetch(&(x), y, __ATOMIC_SEQ_CST)
+#define ATOMIC_POST_OR(x, y) __atomic_fetch_or(&(x), y, __ATOMIC_SEQ_CST)
+
+#define ATOMIC_PRE_INC_RELAXED(x) __atomic_add_fetch(&(x), 1, __ATOMIC_RELAXED)
+#define ATOMIC_POST_OR_RELAXED(x, y) __atomic_fetch_or(&(x), y, __ATOMIC_RELAXED)
+
+__attribute__((always_inline)) static inline uint8_t ATOMIC_BTS(uint8_t* addr, size_t offset) {
+ uint8_t oldbit;
+ addr += (offset / 8);
+ oldbit = ATOMIC_POST_OR_RELAXED(*addr, ((uint8_t)1U << (offset % 8)));
+ return oldbit;
+}
+
+extern void* util_Malloc(size_t sz);
+
+extern void* util_Calloc(size_t sz);
+
+extern void* util_MMap(size_t sz);
+
+extern void* util_Realloc(void* ptr, size_t sz);
+
+extern char* util_StrDup(const char* s);
+
+extern uint64_t util_rndGet(uint64_t min, uint64_t max);
+
+extern void util_rndBuf(uint8_t* buf, size_t sz);
+
+extern uint64_t util_rnd64(void);
+
+extern int util_ssnprintf(char* str, size_t size, const char* format, ...);
+
+extern int util_vssnprintf(char* str, size_t size, const char* format, va_list ap);
+
+extern void util_getLocalTime(const char* fmt, char* buf, size_t len, time_t tm);
+
+extern void util_nullifyStdio(void);
+
+extern bool util_redirectStdin(const char* inputFile);
+
+extern uint64_t util_hash(const char* buf, size_t len);
+
+extern int64_t util_timeNowMillis(void);
+
+extern uint64_t util_getUINT32(const uint8_t* buf);
+extern uint64_t util_getUINT64(const uint8_t* buf);
+
+extern void util_mutexLock(pthread_mutex_t* mutex, const char* func, int line);
+extern void util_mutexUnlock(pthread_mutex_t* mutex, const char* func, int line);
+
+extern void util_mutexRWLockRead(pthread_rwlock_t* mutex, const char* func, int line);
+extern void util_mutexRWLockWrite(pthread_rwlock_t* mutex, const char* func, int line);
+extern void util_mutexRWUnlock(pthread_rwlock_t* mutex, const char* func, int line);
+
+extern int64_t fastArray64Search(uint64_t* array, size_t arraySz, uint64_t key);
+
+extern bool util_isANumber(const char* s);
+
+extern size_t util_decodeCString(char* s);
+
+extern uint64_t util_CRC64(const uint8_t* buf, size_t len);
+extern uint64_t util_CRC64Rev(const uint8_t* buf, size_t len);
+
+#endif /* ifndef _HF_COMMON_UTIL_H_ */