blob: 026d599f884c4b58feb76fa6eb21e9b8433c3cd7 [file] [log] [blame]
/*
*
* 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 "common.h"
#include "util.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 <ctype.h>
#include "files.h"
#include "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 | MAP_NORESERVE, -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 rndX;
/* MMIX LCG PRNG */
static const uint64_t a = 6364136223846793005ULL;
static const uint64_t c = 1442695040888963407ULL;
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");
}
defer {
close(fd);
};
if (files_readFromFd(fd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
}
}
uint64_t util_rnd64(void)
{
pthread_once(&rndThreadOnce, util_rndInitThread);
rndX = a * rndX + c;
return rndX;
}
uint64_t util_rndGet(uint64_t min, uint64_t max)
{
if (min > max) {
LOG_F("min:%" PRIu64 " > max:%" PRIu64, min, max);
}
return ((util_rnd64() % (max - min + 1)) + min);
}
void util_rndBuf(uint8_t * buf, size_t sz)
{
if (sz == 0) {
return;
}
pthread_once(&rndThreadOnce, util_rndInitThread);
for (size_t i = 0; i < sz; i++) {
rndX = a * rndX + c;
buf[i] = (uint8_t) (rndX >> 15);
}
}
/*
* 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);
}
}
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' && i < len; i++, o++) {
switch (s[i]) {
case '\\':{
i++;
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] = ' ';
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(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;
}