blob: 20e6c090e962823a5630b4a4a966b9f6bee94033 [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com81189852015-02-14 23:44:55 +00003 * honggfuzz - file operations
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 "common.h"
25#include "files.h"
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000026
27#include <dirent.h>
28#include <errno.h>
29#include <fcntl.h>
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +000030#include <inttypes.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000031#include <stdint.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/mman.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <unistd.h>
39
robert.swiecki3bb518c2010-10-14 00:48:24 +000040#include "log.h"
Robert Swiecki0fc5e942016-03-15 15:49:12 +010041#include "util.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000042
Robert Swieckidecf14b2016-03-31 15:09:28 +020043ssize_t files_readFileToBufMax(char *fileName, uint8_t * buf, size_t fileMaxSz)
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000044{
45 int fd = open(fileName, O_RDONLY);
46 if (fd == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020047 PLOG_E("Couldn't open '%s' for R/O", fileName);
Robert Swieckidecf14b2016-03-31 15:09:28 +020048 return -1;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000049 }
Jagger4fe18692016-04-22 23:15:07 +020050 defer {
51 close(fd);
52 };
Robert Swieckia9db9dd2016-03-09 16:29:37 +010053
Robert Swieckidecf14b2016-03-31 15:09:28 +020054 ssize_t readSz = files_readFromFd(fd, buf, fileMaxSz);
55 if (readSz < 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020056 LOG_E("Couldn't read '%s' to a buf", fileName);
Jagger1aa94d72016-04-02 02:37:35 +020057 return -1;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000058 }
59
Jagger4d109852016-02-04 02:28:44 +010060 LOG_D("Read '%zu' bytes from '%s'", readSz, fileName);
Jagger4d109852016-02-04 02:28:44 +010061 return readSz;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000062}
63
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000064bool files_writeBufToFile(char *fileName, uint8_t * buf, size_t fileSz, int flags)
65{
66 int fd = open(fileName, flags, 0644);
67 if (fd == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020068 PLOG_E("Couldn't open '%s' for R/O", fileName);
robert.swiecki@gmail.com276f9f12015-03-01 01:39:47 +000069 return false;
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000070 }
Jagger4fe18692016-04-22 23:15:07 +020071 defer {
72 close(fd);
73 };
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000074
75 if (files_writeToFd(fd, buf, fileSz) == false) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020076 PLOG_E("Couldn't write '%zu' bytes to file '%s' (fd='%d')", fileSz, fileName, fd);
robert.swiecki@gmail.com9be63de2015-03-02 07:08:45 +000077 unlink(fileName);
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000078 return false;
79 }
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000080
Robert Swieckic8c32db2015-10-09 18:06:22 +020081 LOG_D("Written '%zu' bytes to '%s'", fileSz, fileName);
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +000082 return true;
83}
84
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000085bool files_writeToFd(int fd, uint8_t * buf, size_t fileSz)
robert.swiecki3bb518c2010-10-14 00:48:24 +000086{
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000087 size_t writtenSz = 0;
88 while (writtenSz < fileSz) {
89 ssize_t sz = write(fd, &buf[writtenSz], fileSz - writtenSz);
robert.swiecki3bb518c2010-10-14 00:48:24 +000090 if (sz < 0 && errno == EINTR)
91 continue;
92
93 if (sz < 0)
94 return false;
95
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +000096 writtenSz += sz;
robert.swiecki3bb518c2010-10-14 00:48:24 +000097 }
robert.swiecki3bb518c2010-10-14 00:48:24 +000098 return true;
99}
100
robert.swiecki@gmail.comad6af222015-02-14 01:56:08 +0000101bool files_writeStrToFd(int fd, char *str)
102{
103 return files_writeToFd(fd, (uint8_t *) str, strlen(str));
104}
105
Robert Swieckidecf14b2016-03-31 15:09:28 +0200106ssize_t files_readFromFd(int fd, uint8_t * buf, size_t fileSz)
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000107{
108 size_t readSz = 0;
109 while (readSz < fileSz) {
110 ssize_t sz = read(fd, &buf[readSz], fileSz - readSz);
111 if (sz < 0 && errno == EINTR)
112 continue;
113
Robert Swieckidecf14b2016-03-31 15:09:28 +0200114 if (sz == 0)
Jagger4d109852016-02-04 02:28:44 +0100115 break;
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000116
Robert Swieckidecf14b2016-03-31 15:09:28 +0200117 if (sz < 0)
118 return -1;
119
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000120 readSz += sz;
121 }
Robert Swieckidecf14b2016-03-31 15:09:28 +0200122 return (ssize_t) readSz;
robert.swiecki@gmail.com26a9ab72015-02-22 13:41:18 +0000123}
124
groebert@google.com1bd4c212013-06-19 11:13:56 +0000125bool files_exists(char *fileName)
126{
127 return (access(fileName, F_OK) != -1);
128}
129
robert.swiecki3bb518c2010-10-14 00:48:24 +0000130bool files_writePatternToFd(int fd, off_t size, unsigned char p)
131{
132 void *buf = malloc(size);
133 if (!buf) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200134 PLOG_W("Couldn't allocate memory");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000135 return false;
136 }
Jagger4fe18692016-04-22 23:15:07 +0200137 defer {
138 free(buf);
139 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000140
141 memset(buf, p, (size_t) size);
142 int ret = files_writeToFd(fd, buf, size);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000143
144 return ret;
145}
146
robert.swiecki3bb518c2010-10-14 00:48:24 +0000147static bool files_readdir(honggfuzz_t * hfuzz)
148{
149 DIR *dir = opendir(hfuzz->inputFile);
150 if (!dir) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200151 PLOG_E("Couldn't open dir '%s'", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000152 return false;
153 }
Jagger4fe18692016-04-22 23:15:07 +0200154 defer {
155 closedir(dir);
156 };
robert.swiecki3bb518c2010-10-14 00:48:24 +0000157
158 int count = 0;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000159 for (;;) {
160 struct dirent de, *res;
161 if (readdir_r(dir, &de, &res) > 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200162 PLOG_E("Couldn't read the '%s' dir", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000163 return false;
164 }
165
166 if (res == NULL && count > 0) {
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200167 LOG_I("%zu input files have been added to the list", hfuzz->fileCnt);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000168 return true;
169 }
170
171 if (res == NULL && count == 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200172 LOG_E("Directory '%s' doesn't contain any regular files", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000173 return false;
174 }
175
176 char path[PATH_MAX];
177 snprintf(path, sizeof(path), "%s/%s", hfuzz->inputFile, res->d_name);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000178 struct stat st;
179 if (stat(path, &st) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200180 LOG_W("Couldn't stat() the '%s' file", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000181 continue;
182 }
183
184 if (!S_ISREG(st.st_mode)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200185 LOG_D("'%s' is not a regular file, skipping", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000186 continue;
187 }
188
robert.swiecki@gmail.comc1b759b2015-03-01 18:41:15 +0000189 if (st.st_size == 0ULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200190 LOG_D("'%s' is empty", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000191 continue;
192 }
193
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +0000194 if (st.st_size > (off_t) hfuzz->maxFileSz) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200195 LOG_W("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %"
196 PRId64, path, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
robert.swiecki@gmail.com86941cb2015-02-22 15:15:08 +0000197 continue;
198 }
199
robert.swiecki3bb518c2010-10-14 00:48:24 +0000200 if (!(hfuzz->files = realloc(hfuzz->files, sizeof(char *) * (count + 1)))) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200201 PLOG_E("Couldn't allocate memory");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000202 return false;
203 }
204
Jagger6539b3a2016-04-06 02:32:50 +0200205 hfuzz->files[count] = util_StrDup(path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000206 hfuzz->fileCnt = ++count;
Robert Swieckic8c32db2015-10-09 18:06:22 +0200207 LOG_D("Added '%s' to the list of input files", path);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000208 }
209
210 abort(); /* NOTREACHED */
211 return false;
212}
213
214bool files_init(honggfuzz_t * hfuzz)
215{
Robert Swiecki3a94db72016-03-15 15:48:33 +0100216 hfuzz->files = util_Malloc(sizeof(char *));
Jaggera34b3022016-04-02 02:20:40 +0200217 hfuzz->files[0] = "NONE";
Jagger30384ec2016-04-02 02:30:32 +0200218 hfuzz->fileCnt = 1;
Jaggera34b3022016-04-02 02:20:40 +0200219
220 if (hfuzz->externalCommand) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200221 LOG_I
Jaggera34b3022016-04-02 02:20:40 +0200222 ("No input file corpus loaded, the external command '%s' is responsible for creating the fuzz files",
Robert Swieckic8c32db2015-10-09 18:06:22 +0200223 hfuzz->externalCommand);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000224 return true;
225 }
226
robert.swiecki3bb518c2010-10-14 00:48:24 +0000227 if (!hfuzz->inputFile) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200228 LOG_E("No input file/dir specified");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000229 return false;
230 }
231
232 struct stat st;
233 if (stat(hfuzz->inputFile, &st) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200234 PLOG_E("Couldn't stat the input file/dir '%s'", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000235 return false;
236 }
237
238 if (S_ISDIR(st.st_mode)) {
239 return files_readdir(hfuzz);
240 }
241
242 if (!S_ISREG(st.st_mode)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200243 LOG_E("'%s' is not a regular file, nor a directory", hfuzz->inputFile);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000244 return false;
245 }
246
robert.swiecki@gmail.com2e0103f2015-03-30 01:38:12 +0000247 if (st.st_size > (off_t) hfuzz->maxFileSz) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200248 LOG_E("File '%s' is bigger than maximal defined file size (-F): %" PRId64 " > %" PRId64,
249 hfuzz->inputFile, (int64_t) st.st_size, (int64_t) hfuzz->maxFileSz);
robert.swiecki@gmail.com2e0103f2015-03-30 01:38:12 +0000250 return false;
251 }
252
robert.swiecki3bb518c2010-10-14 00:48:24 +0000253 hfuzz->files[0] = hfuzz->inputFile;
254 hfuzz->fileCnt = 1;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000255 return true;
256}
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000257
Robert Swieckidecf14b2016-03-31 15:09:28 +0200258const char *files_basename(char *path)
groebert@google.com1bd4c212013-06-19 11:13:56 +0000259{
Robert Swieckidecf14b2016-03-31 15:09:28 +0200260 const char *base = strrchr(path, '/');
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000261 return base ? base + 1 : path;
262}
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000263
264bool files_parseDictionary(honggfuzz_t * hfuzz)
265{
266 FILE *fDict = fopen(hfuzz->dictionaryFile, "rb");
267 if (fDict == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200268 PLOG_E("Couldn't open '%s' - R/O mode", hfuzz->dictionaryFile);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000269 return false;
270 }
Jagger4fe18692016-04-22 23:15:07 +0200271 defer {
272 fclose(fDict);
273 };
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000274
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000275 for (;;) {
Robert Swieckicaf9d762016-03-10 16:13:18 +0100276 char *lineptr = NULL;
277 size_t n = 0;
robert.swiecki@gmail.com0440c532015-04-21 17:27:08 +0000278 if (getdelim(&lineptr, &n, '\0', fDict) == -1) {
279 break;
280 }
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000281 if ((hfuzz->dictionary =
282 realloc(hfuzz->dictionary,
robert.swiecki@gmail.comd9363be2015-04-21 17:24:02 +0000283 (hfuzz->dictionaryCnt + 1) * sizeof(hfuzz->dictionary[0]))) == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200284 PLOG_E("Realloc failed (sz=%zu)",
285 (hfuzz->dictionaryCnt + 1) * sizeof(hfuzz->dictionary[0]));
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000286 return false;
287 }
Robert Swieckicaf9d762016-03-10 16:13:18 +0100288 hfuzz->dictionary[hfuzz->dictionaryCnt] = lineptr;
Robert Swieckic8c32db2015-10-09 18:06:22 +0200289 LOG_D("Dictionary: loaded word: '%s' (len=%zu)",
290 hfuzz->dictionary[hfuzz->dictionaryCnt],
291 strlen(hfuzz->dictionary[hfuzz->dictionaryCnt]));
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000292 hfuzz->dictionaryCnt += 1;
293 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200294 LOG_I("Loaded %zu words from the dictionary", hfuzz->dictionaryCnt);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000295 return true;
296}
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300297
298/*
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300299 * dstExists argument can be used by caller for cases where existing destination
300 * file requires special handling (e.g. save unique crashes)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300301 */
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300302bool files_copyFile(const char *source, const char *destination, bool * dstExists)
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300303{
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300304 if (dstExists)
305 *dstExists = false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300306 if (link(source, destination) == 0) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300307 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300308 } else {
309 if (errno == EEXIST) {
310 // Should kick-in before MAC, so avoid the hassle
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300311 if (dstExists)
312 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300313 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300314 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200315 PLOG_D("Couldn't link '%s' as '%s'", source, destination);
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300316 /*
317 * Don't fail yet as we might have a running env which doesn't allow
318 * hardlinks (e.g. SELinux)
319 */
320 }
321 }
322
323 // Now try with a verbose POSIX alternative
324 int inFD, outFD, dstOpenFlags;
325 mode_t dstFilePerms;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300326
327 // O_EXCL is important for saving unique crashes
328 dstOpenFlags = O_CREAT | O_WRONLY | O_EXCL;
329 dstFilePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
330
331 inFD = open(source, O_RDONLY);
332 if (inFD == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200333 PLOG_D("Couldn't open '%s' source", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300334 return false;
335 }
Jagger4fe18692016-04-22 23:15:07 +0200336 defer {
337 close(inFD);
338 };
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300339
340 struct stat inSt;
341 if (fstat(inFD, &inSt) == -1) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200342 PLOG_E("Couldn't fstat(fd='%d' fileName='%s')", inFD, source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300343 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300344 }
345
346 outFD = open(destination, dstOpenFlags, dstFilePerms);
347 if (outFD == -1) {
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300348 if (errno == EEXIST) {
Anestis Bechtsoudis38773212015-09-08 23:34:28 +0300349 if (dstExists)
350 *dstExists = true;
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300351 }
Robert Swieckic8c32db2015-10-09 18:06:22 +0200352 PLOG_D("Couldn't open '%s' destination", destination);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300353 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300354 }
Jagger4fe18692016-04-22 23:15:07 +0200355 defer {
356 close(outFD);
357 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300358
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300359 uint8_t *inFileBuf = malloc(inSt.st_size);
360 if (!inFileBuf) {
Anestis Bechtsoudisc9473322015-10-09 12:59:17 -0700361 PLOG_E("malloc(%zu) failed", (size_t) inSt.st_size);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300362 return false;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300363 }
Jagger4fe18692016-04-22 23:15:07 +0200364 defer {
365 free(inFileBuf);
366 };
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300367
Robert Swieckidecf14b2016-03-31 15:09:28 +0200368 ssize_t readSz = files_readFromFd(inFD, inFileBuf, (size_t) inSt.st_size);
369 if (readSz < 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200370 PLOG_E("Couldn't read '%s' to a buf", source);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300371 return false;
372 }
373
Jagger4d109852016-02-04 02:28:44 +0100374 if (files_writeToFd(outFD, inFileBuf, readSz) == false) {
375 PLOG_E("Couldn't write '%zu' bytes to file '%s' (fd='%d')", (size_t) readSz,
Robert Swieckic8c32db2015-10-09 18:06:22 +0200376 destination, outFD);
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300377 unlink(destination);
378 return false;
379 }
380
Anestis Bechtsoudis1ae1ce12015-09-06 23:43:48 +0300381 return true;
Anestis Bechtsoudis7d42f9d2015-09-06 14:30:20 +0300382}
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300383
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300384bool files_parseBlacklist(honggfuzz_t * hfuzz)
385{
386 FILE *fBl = fopen(hfuzz->blacklistFile, "rb");
387 if (fBl == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200388 PLOG_E("Couldn't open '%s' - R/O mode", hfuzz->blacklistFile);
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300389 return false;
390 }
Jagger4fe18692016-04-22 23:15:07 +0200391 defer {
392 fclose(fBl);
393 };
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300394
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200395 char *lineptr = NULL;
Jagger1dad1822016-03-29 23:56:14 +0200396 /* lineptr can be NULL, but it's fine for free() */
Jagger4fe18692016-04-22 23:15:07 +0200397 defer {
398 free(lineptr);
399 };
Anestis Bechtsoudis3a8e16f2016-01-10 15:06:09 +0200400 size_t n = 0;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300401 for (;;) {
Anestis Bechtsoudis7d6185c2015-09-21 15:59:56 +0300402 if (getline(&lineptr, &n, fBl) == -1) {
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300403 break;
404 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300405
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300406 if ((hfuzz->blacklist =
407 realloc(hfuzz->blacklist,
408 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]))) == NULL) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200409 PLOG_E("realloc failed (sz=%zu)",
410 (hfuzz->blacklistCnt + 1) * sizeof(hfuzz->blacklist[0]));
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300411 return false;
412 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300413
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300414 hfuzz->blacklist[hfuzz->blacklistCnt] = strtoull(lineptr, 0, 16);
Anestis Bechtsoudis07e14ce2015-12-30 14:15:42 +0200415 LOG_D("Blacklist: loaded %'" PRIu64 "'", hfuzz->blacklist[hfuzz->blacklistCnt]);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300416
417 // Verify entries are sorted so we can use interpolation search
418 if (hfuzz->blacklistCnt > 1) {
419 if (hfuzz->blacklist[hfuzz->blacklistCnt - 1] > hfuzz->blacklist[hfuzz->blacklistCnt]) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200420 LOG_F
421 ("Blacklist file not sorted. Use 'tools/createStackBlacklist.sh' to sort records");
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300422 return false;
423 }
424 }
Anestis Bechtsoudis612baa52015-09-23 18:21:43 +0300425 hfuzz->blacklistCnt += 1;
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300426 }
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300427
Anestis Bechtsoudisebf879e2015-09-27 18:11:25 +0300428 if (hfuzz->blacklistCnt > 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200429 LOG_I("Loaded %zu stack hash(es) from the blacklist file", hfuzz->blacklistCnt);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300430 } else {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200431 LOG_F("Empty stack hashes blacklist file '%s'", hfuzz->blacklistFile);
Anestis Bechtsoudis99db8742015-09-23 11:37:26 +0300432 }
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300433 return true;
434}
Anestis Bechtsoudisee5316d2015-09-27 19:11:48 +0300435
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300436uint8_t *files_mapFile(char *fileName, off_t * fileSz, int *fd, bool isWritable)
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300437{
438 int mmapProt = PROT_READ;
439 if (isWritable) {
440 mmapProt |= PROT_WRITE;
441 }
442
443 if ((*fd = open(fileName, O_RDONLY)) == -1) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700444 PLOG_E("Couldn't open() '%s' file in R/O mode", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300445 return NULL;
446 }
447
448 struct stat st;
449 if (fstat(*fd, &st) == -1) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700450 PLOG_E("Couldn't stat() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300451 close(*fd);
452 return NULL;
453 }
454
455 uint8_t *buf;
456 if ((buf = mmap(NULL, st.st_size, mmapProt, MAP_PRIVATE, *fd, 0)) == MAP_FAILED) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700457 PLOG_E("Couldn't mmap() the '%s' file", fileName);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300458 close(*fd);
459 return NULL;
460 }
461
462 *fileSz = st.st_size;
463 return buf;
464}
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200465
466bool files_readPidFromFile(const char *fileName, pid_t * pidPtr)
467{
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200468 FILE *fPID = fopen(fileName, "rb");
469 if (fPID == NULL) {
470 PLOG_E("Couldn't open '%s' - R/O mode", fileName);
471 return false;
472 }
Jagger4fe18692016-04-22 23:15:07 +0200473 defer {
474 fclose(fPID);
475 };
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200476
477 char *lineptr = NULL;
478 size_t lineSz = 0;
479 if (getline(&lineptr, &lineSz, fPID) == -1) {
480 if (lineSz == 0) {
481 LOG_E("Empty PID file (%s)", fileName);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100482 return false;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200483 }
484 }
Jagger4fe18692016-04-22 23:15:07 +0200485 defer {
486 free(lineptr);
487 };
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200488
489 *pidPtr = atoi(lineptr);
490 if (*pidPtr < 1) {
491 LOG_E("Invalid PID read from '%s' file", fileName);
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100492 return false;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200493 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200494
Robert Swieckia9db9dd2016-03-09 16:29:37 +0100495 return true;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200496}