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, &ltime);
148     if (strftime(buf, len, fmt, &ltime) < 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