1 /*
2 *
3 * honggfuzz - utilities
4 * -----------------------------------------
5 *
6 * Author: Robert Swiecki <swiecki@google.com>
7 *
8 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
9 *
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
12 * a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * 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.
21 *
22 */
23
24 #include <fcntl.h>
25 #include <inttypes.h>
26 #include <math.h>
27 #include <stdarg.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <ctype.h>
38
39 #include "common.h"
40 #include "files.h"
41 #include "log.h"
42
43 #if defined(__builtin_bswap16)
44 #define SWAP16(x) __builtin_bswap16(x)
45 #else
46 #define SWAP16(x) ((x & 0xff) << 8) | ((x & 0xff00) >> 8)
47 #endif
48
49 #if defined(__builtin_bswap32)
50 #define SWAP32(x) __builtin_bswap32(x)
51 #else
52 #define SWAP32(x) ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24)
53 #endif
54
util_Malloc(size_t sz)55 void *util_Malloc(size_t sz)
56 {
57 void *p = malloc(sz);
58 if (p == NULL) {
59 LOG_F("malloc(size='%zu')", sz);
60 }
61 return p;
62 }
63
64 static int util_urandomFd = -1;
65 static __thread uint64_t rndX;
66 static __thread uint64_t rndIni = false;
67
util_rndGet(uint64_t min,uint64_t max)68 uint64_t util_rndGet(uint64_t min, uint64_t max)
69 {
70 if (min > max) {
71 LOG_F("min:%" PRIu64 " > max:%" PRIu64, min, max);
72 }
73
74 if (util_urandomFd == -1) {
75 if ((util_urandomFd = open("/dev/urandom", O_RDONLY)) == -1) {
76 PLOG_F("Couldn't open /dev/urandom for writing");
77 }
78 }
79
80 if (rndIni == false) {
81 if (files_readFromFd(util_urandomFd, (uint8_t *) & rndX, sizeof(rndX)) != sizeof(rndX)) {
82 PLOG_F("Couldn't read '%zu' bytes from /dev/urandom", sizeof(rndX));
83 }
84 rndIni = true;
85 }
86
87 /* MMIX LCG PRNG */
88 static const uint64_t a = 6364136223846793005ULL;
89 static const uint64_t c = 1442695040888963407ULL;
90
91 rndX = (a * rndX + c);
92
93 return ((rndX % (max - min + 1)) + min);
94 }
95
util_rndBuf(uint8_t * buf,size_t sz)96 void util_rndBuf(uint8_t * buf, size_t sz)
97 {
98 /* MMIX LCG PRNG */
99 static const uint64_t a = 6364136223846793005ULL;
100 static const uint64_t c = 1442695040888963407ULL;
101 uint64_t x = util_rndGet(0, 1ULL << 62);
102
103 for (size_t i = 0; i < sz; i++) {
104 x = (a * x + c);
105 buf[i] = (uint8_t) (x & 0xFF);
106 }
107 }
108
109 /*
110 * Function has variable length stack size, although already we know it's invoked
111 * with relatively small sizes (max is _HF_REPORT_SIZE), thus safe to silent warning.
112 */
113 #pragma GCC diagnostic push
114 #pragma GCC diagnostic ignored "-Wframe-larger-than="
util_vssnprintf(char * str,size_t size,const char * format,va_list ap)115 int util_vssnprintf(char *str, size_t size, const char *format, va_list ap)
116 {
117 char buf1[size];
118 char buf2[size];
119
120 strncpy(buf1, str, size);
121
122 vsnprintf(buf2, size, format, ap);
123
124 return snprintf(str, size, "%s%s", buf1, buf2);
125 }
126
util_ssnprintf(char * str,size_t size,const char * format,...)127 int util_ssnprintf(char *str, size_t size, const char *format, ...)
128 {
129 char buf1[size];
130 char buf2[size];
131
132 strncpy(buf1, str, size);
133
134 va_list args;
135 va_start(args, format);
136 vsnprintf(buf2, size, format, args);
137 va_end(args);
138
139 return snprintf(str, size, "%s%s", buf1, buf2);
140 }
141
142 #pragma GCC diagnostic pop /* EOF diagnostic ignored "-Wstack-usage=" */
143
util_getLocalTime(const char * fmt,char * buf,size_t len,time_t tm)144 void util_getLocalTime(const char *fmt, char *buf, size_t len, time_t tm)
145 {
146 struct tm ltime;
147 localtime_r(&tm, <ime);
148 if (strftime(buf, len, fmt, <ime) < 1) {
149 snprintf(buf, len, "[date fetch error]");
150 }
151 }
152
util_nullifyStdio(void)153 void util_nullifyStdio(void)
154 {
155 int fd = open("/dev/null", O_RDWR);
156
157 if (fd == -1) {
158 PLOG_E("Couldn't open '/dev/null'");
159 return;
160 }
161
162 dup2(fd, 0);
163 dup2(fd, 1);
164 dup2(fd, 2);
165
166 if (fd > 2) {
167 close(fd);
168 }
169 }
170
util_redirectStdin(const char * inputFile)171 bool util_redirectStdin(const char *inputFile)
172 {
173 int fd = open(inputFile, O_RDONLY);
174
175 if (fd == -1) {
176 PLOG_E("Couldn't open '%s'", inputFile);
177 return false;
178 }
179
180 dup2(fd, 0);
181 if (fd != 0) {
182 close(fd);
183 }
184
185 return true;
186 }
187
188 /*
189 * This is not a cryptographically secure hash
190 */
util_hash(const char * buf,size_t len)191 uint64_t util_hash(const char *buf, size_t len)
192 {
193 uint64_t ret = 0;
194
195 for (size_t i = 0; i < len; i++) {
196 ret += buf[i];
197 ret += (ret << 10);
198 ret ^= (ret >> 6);
199 }
200
201 return ret;
202 }
203
util_timeNowMillis(void)204 int64_t util_timeNowMillis(void)
205 {
206 struct timeval tv;
207 if (gettimeofday(&tv, NULL) == -1) {
208 PLOG_F("gettimeofday()");
209 }
210
211 return (((int64_t) tv.tv_sec * 1000LL) + ((int64_t) tv.tv_usec / 1000LL));
212 }
213
util_ToFromBE16(uint16_t val)214 uint16_t util_ToFromBE16(uint16_t val)
215 {
216 #if __BYTE_ORDER == __BIG_ENDIAN
217 return val;
218 #elif __BYTE_ORDER == __LITTLE_ENDIAN
219 return SWAP16(val);
220 #else
221 #error "Unknown ENDIANNESS"
222 #endif
223 }
224
util_ToFromLE16(uint16_t val)225 uint16_t util_ToFromLE16(uint16_t val)
226 {
227 #if __BYTE_ORDER == __BIG_ENDIAN
228 return SWAP16(val);
229 #elif __BYTE_ORDER == __LITTLE_ENDIAN
230 return val;
231 #else
232 #error "Unknown ENDIANNESS"
233 #endif
234 }
235
util_ToFromBE32(uint32_t val)236 uint32_t util_ToFromBE32(uint32_t val)
237 {
238 #if __BYTE_ORDER == __BIG_ENDIAN
239 return val;
240 #elif __BYTE_ORDER == __LITTLE_ENDIAN
241 return SWAP32(val);
242 #else
243 #error "Unknown ENDIANNESS"
244 #endif
245 }
246
util_ToFromLE32(uint32_t val)247 uint32_t util_ToFromLE32(uint32_t val)
248 {
249 #if __BYTE_ORDER == __BIG_ENDIAN
250 return SWAP32(val);
251 #elif __BYTE_ORDER == __LITTLE_ENDIAN
252 return val;
253 #else
254 #error "Unknown ENDIANNESS"
255 #endif
256 }
257
util_getUINT32(const uint8_t * buf)258 uint64_t util_getUINT32(const uint8_t * buf)
259 {
260 return (uint64_t) (*((uint32_t *) buf));
261 }
262
util_getUINT64(const uint8_t * buf)263 uint64_t util_getUINT64(const uint8_t * buf)
264 {
265 return *((uint64_t *) buf);
266 }
267
util_mutexLock(pthread_mutex_t * mutex,const char * func,int line)268 void util_mutexLock(pthread_mutex_t * mutex, const char *func, int line)
269 {
270 if (pthread_mutex_lock(mutex)) {
271 PLOG_F("%s():%d pthread_mutex_lock(%p)", func, line, mutex);
272 }
273 }
274
util_mutexUnlock(pthread_mutex_t * mutex,const char * func,int line)275 void util_mutexUnlock(pthread_mutex_t * mutex, const char *func, int line)
276 {
277 if (pthread_mutex_unlock(mutex)) {
278 PLOG_F("%s():%d pthread_mutex_unlock(%p)", func, line, mutex);
279 }
280 }
281
fastArray64Search(uint64_t * array,size_t arraySz,uint64_t key)282 int64_t fastArray64Search(uint64_t * array, size_t arraySz, uint64_t key)
283 {
284 size_t low = 0;
285 size_t high = arraySz - 1;
286 size_t mid;
287
288 while (array[high] != array[low] && key >= array[low] && key <= array[high]) {
289 mid = low + (key - array[low]) * ((high - low) / (array[high] - array[low]));
290
291 if (array[mid] < key) {
292 low = mid + 1;
293 } else if (key < array[mid]) {
294 high = mid - 1;
295 } else {
296 return mid;
297 }
298 }
299
300 if (key == array[low]) {
301 return low;
302 } else {
303 return -1;
304 }
305 }
306
util_isANumber(const char * s)307 bool util_isANumber(const char *s)
308 {
309 if (!isdigit(s[0])) {
310 return false;
311 }
312 for (int i = 0; s[i]; s++) {
313 if (!isdigit(s[i]) && s[i] != 'x') {
314 return false;
315 }
316 }
317 return true;
318 }
319