blob: 8779fe0b2022ec45abee194433216fcd47acf61b [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com97c77332015-02-14 23:06:58 +00003 * honggfuzz - utilities
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00006 * Author: Robert Swiecki <swiecki@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00007 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00008 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000012 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000013 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000021 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000022 */
robert.swiecki3bb518c2010-10-14 00:48:24 +000023
robert.swiecki3bb518c2010-10-14 00:48:24 +000024#include <fcntl.h>
Robert Swieckic8c32db2015-10-09 18:06:22 +020025#include <inttypes.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000026#include <math.h>
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000027#include <stdarg.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000028#include <stdint.h>
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000029#include <stdio.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000030#include <stdlib.h>
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000031#include <string.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000032#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/types.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000035#include <time.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000036#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000037
38#include "common.h"
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000039#include "files.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000040#include "log.h"
41
Anestis Bechtsoudis4f9bfd02015-09-10 17:31:58 +030042#if defined(__builtin_bswap16)
43#define SWAP16(x) __builtin_bswap16(x)
44#else
45#define SWAP16(x) ((x & 0xff) << 8) | ((x & 0xff00) >> 8)
46#endif
47
48#if defined(__builtin_bswap32)
49#define SWAP32(x) __builtin_bswap32(x)
50#else
51#define SWAP32(x) ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)
52#endif
53
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000054static int util_urandomFd = -1;
Jagger2e518b52015-09-24 04:01:16 +020055static __thread uint64_t rndX;
56static __thread uint64_t rndIni = false;
robert.swiecki@gmail.com180263f2015-02-13 13:57:15 +000057
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +000058uint64_t util_rndGet(uint64_t min, uint64_t max)
robert.swiecki3bb518c2010-10-14 00:48:24 +000059{
Jagger2e518b52015-09-24 04:01:16 +020060 if (min > max) {
Anestis Bechtsoudis07e14ce2015-12-30 14:15:42 +020061 LOG_F("min:%" PRIu64 " > max:%" PRIu64, min, max);
Jagger2e518b52015-09-24 04:01:16 +020062 }
63
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000064 if (util_urandomFd == -1) {
65 if ((util_urandomFd = open("/dev/urandom", O_RDONLY)) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020066 PLOG_F("Couldn't open /dev/urandom for writing");
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000067 }
robert.swiecki@gmail.com180263f2015-02-13 13:57:15 +000068 }
robert.swiecki3bb518c2010-10-14 00:48:24 +000069
Jagger2e518b52015-09-24 04:01:16 +020070 if (rndIni == false) {
Jagger4d109852016-02-04 02:28:44 +010071 if (files_readFromFd(util_urandomFd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020072 PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
Jagger2e518b52015-09-24 04:01:16 +020073 }
74 rndIni = true;
robert.swiecki@gmail.com4be12dc2015-02-13 14:03:53 +000075 }
robert.swiecki@gmail.com180263f2015-02-13 13:57:15 +000076
Jagger2e518b52015-09-24 04:01:16 +020077 /* MMIX LCG PRNG */
78 static const uint64_t a = 6364136223846793005ULL;
79 static const uint64_t c = 1442695040888963407ULL;
robert.swiecki@gmail.combce825a2015-02-13 23:26:07 +000080
Jagger2e518b52015-09-24 04:01:16 +020081 rndX = (a * rndX + c);
82
83 return ((rndX % (max - min + 1)) + min);
robert.swiecki3bb518c2010-10-14 00:48:24 +000084}
85
robert.swiecki@gmail.com89cc38c2015-02-23 02:52:08 +000086void util_rndBuf(uint8_t * buf, size_t sz)
87{
robert.swiecki@gmail.comace40862015-03-08 07:09:56 +000088 /* MMIX LCG PRNG */
Jagger89085f92015-09-24 04:45:53 +020089 static const uint64_t a = 6364136223846793005ULL;
90 static const uint64_t c = 1442695040888963407ULL;
91 uint64_t x = util_rndGet(0, 1ULL << 62);
robert.swiecki@gmail.com89cc38c2015-02-23 02:52:08 +000092
robert.swiecki@gmail.com08174c72015-02-28 14:38:06 +000093 for (size_t i = 0; i < sz; i++) {
robert.swiecki@gmail.comace40862015-03-08 07:09:56 +000094 x = (a * x + c);
Jagger89085f92015-09-24 04:45:53 +020095 buf[i] = (uint8_t) (x & 0xFF);
robert.swiecki@gmail.com89cc38c2015-02-23 02:52:08 +000096 }
robert.swiecki@gmail.com89cc38c2015-02-23 02:52:08 +000097}
98
Robert Swiecki23ec02a2016-01-19 18:47:45 +010099/*
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200100 * Function has variable length stack size, although already we know it's invoked
101 * with relatively small sizes (max is _HF_REPORT_SIZE), thus safe to silent warning.
102 */
103#pragma GCC diagnostic push
Anestis Bechtsoudis539dbc52015-12-26 20:11:46 +0200104#pragma GCC diagnostic ignored "-Wframe-larger-than="
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000105int util_vssnprintf(char *str, size_t size, const char *format, va_list ap)
106{
107 char buf1[size];
108 char buf2[size];
109
110 strncpy(buf1, str, size);
111
112 vsnprintf(buf2, size, format, ap);
113
114 return snprintf(str, size, "%s%s", buf1, buf2);
115}
116
117int util_ssnprintf(char *str, size_t size, const char *format, ...)
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000118{
119 char buf1[size];
120 char buf2[size];
121
122 strncpy(buf1, str, size);
123
124 va_list args;
125 va_start(args, format);
126 vsnprintf(buf2, size, format, args);
127 va_end(args);
128
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000129 return snprintf(str, size, "%s%s", buf1, buf2);
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000130}
131
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200132#pragma GCC diagnostic pop /* EOF diagnostic ignored "-Wstack-usage=" */
133
Robert Swiecki81c6a0d2015-09-08 15:43:20 +0200134void util_getLocalTime(const char *fmt, char *buf, size_t len, time_t tm)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000135{
136 struct tm ltime;
Robert Swiecki81c6a0d2015-09-08 15:43:20 +0200137 localtime_r(&tm, &ltime);
138 if (strftime(buf, len, fmt, &ltime) < 1) {
139 snprintf(buf, len, "[date fetch error]");
140 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000141}
142
robert.swiecki40499ff2010-12-13 19:47:08 +0000143void util_nullifyStdio(void)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000144{
145 int fd = open("/dev/null", O_RDWR);
146
147 if (fd == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200148 PLOG_E("Couldn't open '/dev/null'");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000149 return;
150 }
151
152 dup2(fd, 0);
153 dup2(fd, 1);
154 dup2(fd, 2);
155
156 if (fd > 2) {
157 close(fd);
158 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000159}
160
161bool util_redirectStdin(char *inputFile)
162{
163 int fd = open(inputFile, O_RDONLY);
164
165 if (fd == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200166 PLOG_E("Couldn't open '%s'", inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000167 return false;
168 }
169
170 dup2(fd, 0);
171 if (fd != 0) {
172 close(fd);
173 }
174
175 return true;
176}
177
robert.swiecki40499ff2010-12-13 19:47:08 +0000178void util_recoverStdio(void)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000179{
180 int fd = open("/dev/tty", O_RDWR);
181
182 if (fd == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200183 PLOG_E("Couldn't open '/dev/tty'");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000184 return;
185 }
186
187 dup2(fd, 0);
188 dup2(fd, 1);
189 dup2(fd, 2);
190
robert.swiecki@gmail.comdf286942015-04-15 21:45:25 +0000191 if (tcsetpgrp(fd, getpid()) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200192 PLOG_W("tcsetpgrp(%d) failed", getpid());
robert.swiecki@gmail.comdf286942015-04-15 21:45:25 +0000193 }
194
robert.swiecki3bb518c2010-10-14 00:48:24 +0000195 if (fd > 2) {
196 close(fd);
197 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000198}
groebert@google.com1bd4c212013-06-19 11:13:56 +0000199
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000200/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +0000201 * This is not a cryptographically secure hash
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000202 */
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200203uint64_t util_hash(const char *buf, size_t len)
groebert@google.com1bd4c212013-06-19 11:13:56 +0000204{
205 uint64_t ret = 0;
206
207 for (size_t i = 0; i < len; i++) {
208 ret += buf[i];
209 ret += (ret << 10);
210 ret ^= (ret >> 6);
211 }
212
213 return ret;
214}
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000215
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200216int64_t util_timeNowMillis(void)
robert.swiecki@gmail.com3213a112015-03-12 01:42:02 +0000217{
218 struct timeval tv;
219 if (gettimeofday(&tv, NULL) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200220 PLOG_F("gettimeofday()");
robert.swiecki@gmail.com3213a112015-03-12 01:42:02 +0000221 }
222
223 return (((int64_t) tv.tv_sec * 1000LL) + ((int64_t) tv.tv_usec / 1000LL));
224}
225
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200226uint16_t util_ToFromBE16(uint16_t val)
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000227{
228#if __BYTE_ORDER == __BIG_ENDIAN
229 return val;
230#elif __BYTE_ORDER == __LITTLE_ENDIAN
Anestis Bechtsoudis4f9bfd02015-09-10 17:31:58 +0300231 return SWAP16(val);
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000232#else
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200233#error "Unknown ENDIANNESS"
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000234#endif
235}
236
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200237uint16_t util_ToFromLE16(uint16_t val)
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000238{
239#if __BYTE_ORDER == __BIG_ENDIAN
Anestis Bechtsoudis4f9bfd02015-09-10 17:31:58 +0300240 return SWAP16(val);
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000241#elif __BYTE_ORDER == __LITTLE_ENDIAN
242 return val;
243#else
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200244#error "Unknown ENDIANNESS"
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000245#endif
246}
247
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200248uint32_t util_ToFromBE32(uint32_t val)
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000249{
250#if __BYTE_ORDER == __BIG_ENDIAN
251 return val;
252#elif __BYTE_ORDER == __LITTLE_ENDIAN
Anestis Bechtsoudis4f9bfd02015-09-10 17:31:58 +0300253 return SWAP32(val);
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000254#else
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200255#error "Unknown ENDIANNESS"
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000256#endif
257}
258
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200259uint32_t util_ToFromLE32(uint32_t val)
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000260{
261#if __BYTE_ORDER == __BIG_ENDIAN
Anestis Bechtsoudis4f9bfd02015-09-10 17:31:58 +0300262 return SWAP32(val);
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000263#elif __BYTE_ORDER == __LITTLE_ENDIAN
264 return val;
265#else
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200266#error "Unknown ENDIANNESS"
267#endif
268}
269
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200270uint64_t util_getUINT32(const uint8_t * buf)
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200271{
272 const uint8_t b0 = buf[0], b1 = buf[1], b2 = buf[2], b3 = buf[3];
273
274#if __BYTE_ORDER == __BIG_ENDIAN
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200275 return (uint64_t) ((uint32_t) b0 << 24) | ((uint32_t) b1 << 16) | ((uint32_t) b2 << 8) |
276 (uint32_t) b3;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200277#elif __BYTE_ORDER == __LITTLE_ENDIAN
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200278 return (uint64_t) ((uint32_t) b3 << 24) | ((uint32_t) b2 << 16) | ((uint32_t) b1 << 8) |
279 (uint32_t) b0;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200280#else
281#error "Unknown ENDIANNESS"
282#endif
283}
284
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200285uint64_t util_getUINT64(const uint8_t * buf)
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200286{
287 const uint8_t b0 = buf[0], b1 = buf[1], b2 = buf[2], b3 = buf[3],
288 b4 = buf[4], b5 = buf[5], b6 = buf[6], b7 = buf[7];
289
290#if __BYTE_ORDER == __BIG_ENDIAN
Anestis Bechtsoudisf2a5bc62015-12-26 18:41:48 +0200291 return ((uint64_t) b0 << 56) | ((uint64_t) b1 << 48) | ((uint64_t) b2 << 40) |
292 ((uint64_t) b3 << 32) | ((uint64_t) b4 << 24) | ((uint64_t) b5 << 16) |
293 ((uint64_t) b6 << 8) | (uint64_t) b7;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200294#elif __BYTE_ORDER == __LITTLE_ENDIAN
Anestis Bechtsoudisf2a5bc62015-12-26 18:41:48 +0200295 return ((uint64_t) b7 << 56) | ((uint64_t) b6 << 48) | ((uint64_t) b5 << 40) |
296 ((uint64_t) b4 << 32) | ((uint64_t) b3 << 24) | ((uint64_t) b2 << 16) |
297 ((uint64_t) b1 << 8) | (uint64_t) b0;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200298#else
299#error "Unknown ENDIANNESS"
robert.swiecki@gmail.com549ff182015-02-28 22:38:00 +0000300#endif
301}
Jagger421aca82015-09-05 14:09:47 +0200302
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200303void MX_LOCK(pthread_mutex_t * mutex)
Jagger421aca82015-09-05 14:09:47 +0200304{
305 if (pthread_mutex_lock(mutex)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200306 PLOG_F("pthread_mutex_lock(%p)", mutex);
Jagger421aca82015-09-05 14:09:47 +0200307 }
308}
309
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200310void MX_UNLOCK(pthread_mutex_t * mutex)
Jagger421aca82015-09-05 14:09:47 +0200311{
312 if (pthread_mutex_unlock(mutex)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200313 PLOG_F("pthread_mutex_unlock(%p)", mutex);
Jagger421aca82015-09-05 14:09:47 +0200314 }
315}
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300316
Anestis Bechtsoudis38572552016-02-07 12:55:55 +0200317int64_t fastArray64Search(uint64_t * array, size_t arraySz, uint64_t key)
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300318{
319 size_t low = 0;
320 size_t high = arraySz - 1;
321 size_t mid;
322
323 while (array[high] != array[low] && key >= array[low] && key <= array[high]) {
324 mid = low + (key - array[low]) * ((high - low) / (array[high] - array[low]));
325
326 if (array[mid] < key) {
327 low = mid + 1;
328 } else if (key < array[mid]) {
329 high = mid - 1;
330 } else {
331 return mid;
332 }
333 }
334
335 if (key == array[low]) {
336 return low;
337 } else {
338 return -1;
339 }
340}