/* * Returns true if a process exited (so, presumably, we can delete an input * file) */ static bool arch_analyzeSignal(honggfuzz_t * hfuzz, int status, fuzzer_t * fuzzer) { /* * Resumed by delivery of SIGCONT */ if (WIFCONTINUED(status)) { return false; } if (WIFEXITED(status) || WIFSIGNALED(status)) { sancov_Analyze(hfuzz, fuzzer); } /* * Boring, the process just exited */ if (WIFEXITED(status)) { LOG_D("Process (pid %d) exited normally with status %d", fuzzer->pid, WEXITSTATUS(status)); return true; } /* * Shouldn't really happen, but, well.. */ if (!WIFSIGNALED(status)) { LOG_E("Process (pid %d) exited with the following status %d, please report that as a bug", fuzzer->pid, status); return true; } int termsig = WTERMSIG(status); LOG_D("Process (pid %d) killed by signal %d '%s'", fuzzer->pid, termsig, strsignal(termsig)); if (!arch_sigs[termsig].important) { LOG_D("It's not that important signal, skipping"); return true; } /* * Signal is interesting */ /* * Increase crashes counter presented by ASCII display */ ATOMIC_POST_INC(hfuzz->crashesCnt); /* * Get data from exception handler */ fuzzer->pc = g_fuzzer_crash_information[fuzzer->pid].pc; fuzzer->exception = g_fuzzer_crash_information[fuzzer->pid].exception; fuzzer->access = g_fuzzer_crash_information[fuzzer->pid].access; fuzzer->backtrace = g_fuzzer_crash_information[fuzzer->pid].backtrace; defer { if (g_fuzzer_crash_callstack[fuzzer->pid]) { free(g_fuzzer_crash_callstack[fuzzer->pid]); g_fuzzer_crash_callstack[fuzzer->pid] = NULL; } }; /* * Check if stackhash is blacklisted */ if (hfuzz->blacklist && (fastArray64Search(hfuzz->blacklist, hfuzz->blacklistCnt, fuzzer->backtrace) != -1)) { LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace); ATOMIC_POST_INC(hfuzz->blCrashesCnt); return true; } /* If dry run mode, copy file with same name into workspace */ if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) { snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s", hfuzz->workDir, fuzzer->origFileName); } else if (hfuzz->saveUnique) { snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s.%s.PC.%.16llx.STACK.%.16llx.ADDR.%.16llx.%s", hfuzz->workDir, arch_sigs[termsig].descr, exception_to_string(fuzzer->exception), fuzzer->pc, fuzzer->backtrace, fuzzer->access, hfuzz->fileExtn); } else { char localtmstr[PATH_MAX]; util_getLocalTime("%F.%H.%M.%S", localtmstr, sizeof(localtmstr), time(NULL)); snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s.%s.PC.%.16llx.STACK.%.16llx.ADDR.%.16llx.TIME.%s.PID.%.5d.%s", hfuzz->workDir, arch_sigs[termsig].descr, exception_to_string(fuzzer->exception), fuzzer->pc, fuzzer->backtrace, fuzzer->access, localtmstr, fuzzer->pid, hfuzz->fileExtn); } if (files_exists(fuzzer->crashFileName)) { LOG_I("It seems that '%s' already exists, skipping", fuzzer->crashFileName); // Clear filename so that verifier can understand we hit a duplicate memset(fuzzer->crashFileName, 0, sizeof(fuzzer->crashFileName)); return true; } if (files_writeBufToFile (fuzzer->crashFileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz, O_CREAT | O_EXCL | O_WRONLY) == false) { LOG_E("Couldn't copy '%s' to '%s'", fuzzer->fileName, fuzzer->crashFileName); return true; } LOG_I("Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, fuzzer->crashFileName); ATOMIC_POST_INC(hfuzz->uniqueCrashesCnt); /* If unique crash found, reset dynFile counter */ ATOMIC_CLEAR(hfuzz->dynFileIterExpire); arch_generateReport(fuzzer, termsig); return true; }
/* * Called once before fuzzing starts. Prepare mach ports for attaching crash reporter. */ bool arch_archInit(honggfuzz_t * hfuzz) { char plist[PATH_MAX]; snprintf(plist, sizeof(plist), "/Users/%s/Library/Preferences/com.apple.DebugSymbols.plist", getlogin()); if (files_exists(plist)) { LOG_W ("honggfuzz won't work if DBGShellCommands are set in ~/Library/Preferences/com.apple.DebugSymbols.plist"); } /* * Allocate exception port. */ if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &g_exception_port) != KERN_SUCCESS) { return false; } /* * Insert exception receive port. */ if (mach_port_insert_right (mach_task_self(), g_exception_port, g_exception_port, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS) { return false; } /* * Get bootstrap port. */ mach_port_t bootstrap = MACH_PORT_NULL; if (task_get_bootstrap_port(mach_task_self(), &bootstrap) != KERN_SUCCESS) { return false; } /* * Generate and register exception port service. */ snprintf(g_service_name, sizeof(g_service_name), "com.google.code.honggfuzz.%d", (int)util_rndGet(0, 999999)); if (bootstrap_check_in(bootstrap, g_service_name, &g_exception_port) != KERN_SUCCESS) { return false; } /* * Create a collection thread to catch the exceptions from the * children */ pthread_t exception_thread; if (pthread_create(&exception_thread, NULL, wait_for_exception, 0)) { LOG_F("Parent: could not create thread to wait for child's exception"); return false; } if (pthread_detach(exception_thread)) { LOG_F("Parent: could not detach thread to wait for child's exception"); return false; } return true; }
static void arch_ptraceSaveData(honggfuzz_t * hfuzz, pid_t pid, fuzzer_t * fuzzer) { REG_TYPE pc = 0; /* Local copy since flag is overridden for some crashes */ bool saveUnique = hfuzz->saveUnique; char instr[_HF_INSTR_SZ] = "\x00"; siginfo_t si; bzero(&si, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == -1) { PLOG_W("Couldn't get siginfo for pid %d", pid); } arch_getInstrStr(pid, &pc, instr); LOG_D("Pid: %d, signo: %d, errno: %d, code: %d, addr: %p, pc: %" REG_PM ", instr: '%s'", pid, si.si_signo, si.si_errno, si.si_code, si.si_addr, pc, instr); if (!SI_FROMUSER(&si) && pc && si.si_addr < hfuzz->linux.ignoreAddr) { LOG_I("'%s' is interesting (%s), but the si.si_addr is %p (below %p), skipping", fuzzer->fileName, arch_sigs[si.si_signo].descr, si.si_addr, hfuzz->linux.ignoreAddr); return; } /* * Unwind and resolve symbols */ /* *INDENT-OFF* */ funcs_t funcs[_HF_MAX_FUNCS] = { [0 ... (_HF_MAX_FUNCS - 1)].pc = NULL, [0 ... (_HF_MAX_FUNCS - 1)].line = 0, [0 ... (_HF_MAX_FUNCS - 1)].func = {'\0'} , }; /* *INDENT-ON* */ #if !defined(__ANDROID__) size_t funcCnt = arch_unwindStack(pid, funcs); arch_bfdResolveSyms(pid, funcs, funcCnt); #else size_t funcCnt = arch_unwindStack(pid, funcs); #endif /* * If unwinder failed (zero frames), use PC from ptrace GETREGS if not zero. * If PC reg zero, temporarily disable uniqueness flag since callstack * hash will be also zero, thus not safe for unique decisions. */ if (funcCnt == 0) { if (pc) { /* Manually update major frame PC & frames counter */ funcs[0].pc = (void *)(uintptr_t) pc; funcCnt = 1; } else { saveUnique = false; } } /* * Temp local copy of previous backtrace value in case worker hit crashes into multiple * tids for same target master thread. Will be 0 for first crash against target. */ uint64_t oldBacktrace = fuzzer->backtrace; /* * Calculate backtrace callstack hash signature */ arch_hashCallstack(hfuzz, fuzzer, funcs, funcCnt, saveUnique); /* * If fuzzing with sanitizer coverage feedback increase crashes counter used * as metric for dynFile evolution */ if (hfuzz->useSanCov) { fuzzer->sanCovCnts.crashesCnt++; } /* * If unique flag is set and single frame crash, disable uniqueness for this crash * to always save (timestamp will be added to the filename) */ if (saveUnique && (funcCnt == 1)) { saveUnique = false; } /* * If worker crashFileName member is set, it means that a tid has already crashed * from target master thread. */ if (fuzzer->crashFileName[0] != '\0') { LOG_D("Multiple crashes detected from worker against attached tids group"); /* * If stackhashes match, don't re-analyze. This will avoid duplicates * and prevent verifier from running multiple passes. Depth of check is * always 1 (last backtrace saved only per target iteration). */ if (oldBacktrace == fuzzer->backtrace) { return; } } /* Increase global crashes counter */ ATOMIC_POST_INC(hfuzz->crashesCnt); /* * Check if stackhash is blacklisted */ if (hfuzz->blacklist && (fastArray64Search(hfuzz->blacklist, hfuzz->blacklistCnt, fuzzer->backtrace) != -1)) { LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", fuzzer->backtrace); ATOMIC_POST_INC(hfuzz->blCrashesCnt); return; } /* If non-blacklisted crash detected, zero set two MSB */ ATOMIC_POST_ADD(hfuzz->dynFileIterExpire, _HF_DYNFILE_SUB_MASK); void *sig_addr = si.si_addr; if (hfuzz->linux.disableRandomization == false) { pc = 0UL; sig_addr = NULL; } /* User-induced signals don't set si.si_addr */ if (SI_FROMUSER(&si)) { sig_addr = NULL; } /* If dry run mode, copy file with same name into workspace */ if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) { snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s", hfuzz->workDir, fuzzer->origFileName); } else if (saveUnique) { snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s", hfuzz->workDir, arch_sigs[si.si_signo].descr, pc, fuzzer->backtrace, si.si_code, sig_addr, instr, hfuzz->fileExtn); } else { char localtmstr[PATH_MAX]; util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL)); snprintf(fuzzer->crashFileName, sizeof(fuzzer->crashFileName), "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s.%d.%s", hfuzz->workDir, arch_sigs[si.si_signo].descr, pc, fuzzer->backtrace, si.si_code, sig_addr, instr, localtmstr, pid, hfuzz->fileExtn); } if (files_exists(fuzzer->crashFileName)) { LOG_I("It seems that '%s' already exists, skipping", fuzzer->crashFileName); // Clear filename so that verifier can understand we hit a duplicate memset(fuzzer->crashFileName, 0, sizeof(fuzzer->crashFileName)); return; } if (files_writeBufToFile (fuzzer->crashFileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz, O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC) == false) { LOG_E("Couldn't copy '%s' to '%s'", fuzzer->fileName, fuzzer->crashFileName); return; } LOG_I("Ok, that's interesting, saved '%s' as '%s'", fuzzer->fileName, fuzzer->crashFileName); ATOMIC_POST_INC(hfuzz->uniqueCrashesCnt); /* If unique crash found, reset dynFile counter */ ATOMIC_CLEAR(hfuzz->dynFileIterExpire); arch_ptraceGenerateReport(pid, fuzzer, funcs, funcCnt, &si, instr); }
static bool arch_sanCovParseRaw(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) { int dataFd = -1; uint8_t *dataBuf = NULL; off_t dataFileSz = 0, pos = 0; bool is32bit = true, ret = false, isSeedFirstRun = false; char covFile[PATH_MAX] = { 0 }; /* Fuzzer local runtime data structs - need free() before exit */ uint64_t *startMapsIndex = NULL; memMap_t *mapsBuf = NULL; /* Local counters */ uint64_t nBBs = 0; /* Total BB hits found in raw file */ uint64_t nZeroBBs = 0; /* Number of non-hit instrumented BBs */ uint64_t mapsNum = 0; /* Total number of entries in map file */ uint64_t noCovMapsNum = 0; /* Loaded DSOs not compiled with coverage */ /* File line-by-line read help buffers */ char *pLine = NULL; size_t lineSz = 0; /* Coverage data analysis starts by parsing map file listing */ snprintf(covFile, sizeof(covFile), "%s/%s/%d.sancov.map", hfuzz->workDir, _HF_SANCOV_DIR, fuzzer->pid); if (!files_exists(covFile)) { LOG_D("sancov map file not found"); return false; } FILE *fCovMap = fopen(covFile, "rb"); if (fCovMap == NULL) { PLOG_E("Couldn't open '%s' - R/O mode", covFile); goto bail; } /* First line contains PC length (32/64-bit) */ if (getline(&pLine, &lineSz, fCovMap) == -1) { LOG_E("Invalid map file '%s'", covFile); fclose(fCovMap); goto bail; } int pcLen = atoi(pLine); if (pcLen == 32) { is32bit = true; } else if (pcLen == 64) { is32bit = false; } else { LOG_E("Invalid PC length (%d) in map file '%s'", pcLen, covFile); } /* Interaction with global Trie should mutex wrap to avoid threads races */ MX_LOCK(&hfuzz->sanCov_mutex); { /* If runtime data destroy flag, new seed has been picked so destroy old & create new Trie */ if (hfuzz->clearCovMetadata == true) { /* Since this path is invoked on first run too, destroy old Trie only if exists */ if (hfuzz->covMetadata != NULL) { arch_trieDestroy(hfuzz->covMetadata); } arch_trieCreate(&hfuzz->covMetadata); hfuzz->clearCovMetadata = false; isSeedFirstRun = true; } } MX_UNLOCK(&hfuzz->sanCov_mutex); /* See if #maps is available from previous run to avoid realloc inside loop */ uint64_t prevMapsNum = __sync_fetch_and_add(&hfuzz->sanCovCnts.dsoCnt, 0UL); if (prevMapsNum > 0) { if ((mapsBuf = malloc(prevMapsNum * sizeof(memMap_t))) == NULL) { PLOG_E("malloc failed (sz=%" PRIu64 ")", prevMapsNum * sizeof(memMap_t)); /* This will be picked-up later from realloc branch */ prevMapsNum = 0; } } /* Iterate map entries */ for (;;) { if (getline(&pLine, &lineSz, fCovMap) == -1) { break; } /* Trim trailing whitespaces, not sure if needed copied from upstream sancov.py */ char *lineEnd = pLine + strlen(pLine) - 1; while (lineEnd > pLine && isspace(*lineEnd)) { lineEnd--; } *(lineEnd + 1) = 0; /* * Each line has following format: * Start End Base bin/DSO name * b5843000 b584e6ac b5843000 liblog.so */ memMap_t mapData = {.start = 0 }; char *savePtr = NULL; mapData.start = strtoull(strtok_r(pLine, " ", &savePtr), NULL, 16); mapData.end = strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16); mapData.base = strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16); char *mapName = strtok_r(NULL, " ", &savePtr); memcpy(mapData.mapName, mapName, strlen(mapName)); /* Interaction with global Trie should mutex wrap to avoid threads races */ MX_LOCK(&hfuzz->sanCov_mutex); { /* Add entry to Trie with zero data if not already */ if (!arch_trieSearch(hfuzz->covMetadata->children, mapData.mapName)) { arch_trieAdd(&hfuzz->covMetadata, mapData.mapName); } } MX_UNLOCK(&hfuzz->sanCov_mutex); /* If not DSO number history (first run) or new DSO loaded, realloc local maps metadata buf */ if (prevMapsNum == 0 || prevMapsNum < mapsNum) { if ((mapsBuf = realloc(mapsBuf, (size_t) (mapsNum + 1) * sizeof(memMap_t))) == NULL) { PLOG_E("realloc failed (sz=%" PRIu64 ")", (mapsNum + 1) * sizeof(memMap_t)); goto bail; } } /* Add entry to local maps metadata array */ memcpy(&mapsBuf[mapsNum], &mapData, sizeof(memMap_t)); /* Increase loaded maps counter (includes non-instrumented DSOs too) */ mapsNum++; } /* Delete .sancov.map file */ fclose(fCovMap); unlink(covFile); /* Create a quick index array with maps start addresses */ startMapsIndex = malloc(mapsNum * sizeof(uint64_t)); if (startMapsIndex == NULL) { PLOG_E("malloc failed (sz=%" PRIu64 ")", mapsNum * sizeof(uint64_t)); goto bail; } /* Sort quick maps index */ qsort(mapsBuf, mapsNum, sizeof(memMap_t), arch_qsortCmp); for (size_t i = 0; i < mapsNum; i++) { startMapsIndex[i] = mapsBuf[i].start; } /* mmap() .sancov.raw file */ snprintf(covFile, sizeof(covFile), "%s/%s/%d.sancov.raw", hfuzz->workDir, _HF_SANCOV_DIR, fuzzer->pid); dataBuf = files_mapFile(covFile, &dataFileSz, &dataFd, false); if (dataBuf == NULL) { LOG_E("Couldn't open and map '%s' in R/O mode", covFile); goto bail; } /* * Avoid cost of size checks inside raw data read loop by defining the read function * & pivot size based on PC length. */ uint64_t(*pReadRawBBAddrFunc) (const uint8_t *) = NULL; uint8_t pivot = 0; if (is32bit) { pReadRawBBAddrFunc = &util_getUINT32; pivot = 4; } else { pReadRawBBAddrFunc = &util_getUINT64; pivot = 8; } /* * Take advantage of data locality (next processed addr is very likely to belong * to same map) to avoid Trie node search for each read entry. */ node_t *curMap = NULL; uint64_t prevIndex = 0; /* Iterate over data buffer containing list of hit BB addresses */ while (pos < dataFileSz) { uint64_t bbAddr = pReadRawBBAddrFunc(dataBuf + pos); pos += pivot; /* Don't bother for zero BB addr (inserted checks without hit) */ if (bbAddr == 0x0) { nZeroBBs++; continue; } else { /* Find best hit based on start addr & verify range for errors */ uint64_t bestFit = arch_interpSearch(startMapsIndex, mapsNum, bbAddr); if (bbAddr >= mapsBuf[bestFit].start && bbAddr < mapsBuf[bestFit].end) { /* Increase exe/DSO total BB counter */ mapsBuf[bestFit].bbCnt++; /* Update current Trie node if map changed */ if (curMap == NULL || (prevIndex != bestFit)) { prevIndex = bestFit; /* Interaction with global Trie should mutex wrap to avoid threads races */ MX_LOCK(&hfuzz->sanCov_mutex); { curMap = arch_trieSearch(hfuzz->covMetadata->children, mapsBuf[bestFit].mapName); if (curMap == NULL) { LOG_E("Corrupted Trie - '%s' not found", mapsBuf[bestFit].mapName); MX_UNLOCK(&hfuzz->sanCov_mutex); continue; } /* Maintain bitmaps only for exec/DSOs with coverage enabled - allocate on first use */ if (curMap->data.pBM == NULL) { LOG_D("Allocating bitmap for map '%s'", mapsBuf[bestFit].mapName); curMap->data.pBM = arch_newBitmap(_HF_BITMAP_SIZE); /* * If bitmap allocation failed, unset cached Trie node ptr * to execute this selection branch again. */ if (curMap->data.pBM == NULL) { curMap = NULL; MX_UNLOCK(&hfuzz->sanCov_mutex); continue; } } } MX_UNLOCK(&hfuzz->sanCov_mutex); } /* If new relative BB addr update DSO's bitmap */ uint32_t relAddr = (uint32_t) (bbAddr - mapsBuf[bestFit].base); if (!arch_queryBitmap(curMap->data.pBM, relAddr)) { /* Interaction with global Trie should mutex wrap to avoid threads races */ MX_LOCK(&hfuzz->sanCov_mutex); { arch_setBitmap(curMap->data.pBM, relAddr); } MX_UNLOCK(&hfuzz->sanCov_mutex); /* Also increase new BBs counter at worker's thread runtime data */ mapsBuf[bestFit].newBBCnt++; } } else { /* * Normally this should never get executed. If hit, sanitizer * coverage data collection come across some kind of bug. */ LOG_E("Invalid BB addr (%" PRIx64 ") at offset %ld", bbAddr, pos); } } nBBs++; } /* Finally iterate over all instrumented maps to sum-up the number of newly met BB addresses */ for (uint64_t i = 0; i < mapsNum; i++) { if (mapsBuf[i].bbCnt > 0 && !isSeedFirstRun) { fuzzer->sanCovCnts.newBBCnt += mapsBuf[i].newBBCnt; } else { noCovMapsNum++; } } /* Successful parsing - update fuzzer worker's counters */ fuzzer->sanCovCnts.hitBBCnt = nBBs; fuzzer->sanCovCnts.totalBBCnt = nBBs + nZeroBBs; fuzzer->sanCovCnts.dsoCnt = mapsNum; fuzzer->sanCovCnts.iDsoCnt = mapsNum - noCovMapsNum; /* Instrumented DSOs */ ret = true; bail: unlink(covFile); if (dataBuf) { munmap(dataBuf, dataFileSz); } if (dataFd != -1) { close(dataFd); } if (mapsBuf) { free(mapsBuf); } if (startMapsIndex) { free(startMapsIndex); } if (pLine) { free(pLine); } return ret; } static bool arch_sanCovParse(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) { int dataFd = -1; uint8_t *dataBuf = NULL; off_t dataFileSz = 0, pos = 0; bool is32bit = true; char covFile[PATH_MAX] = { 0 }; DIR *pSanCovDir = NULL; bool ret = false; snprintf(covFile, sizeof(covFile), "%s/%s/%s.%d.sancov", hfuzz->workDir, _HF_SANCOV_DIR, files_basename(hfuzz->cmdline[0]), fuzzer->pid); if (!files_exists(covFile)) { LOG_D("Target sancov file not found"); return false; } /* Local cache file suffix to use for file search of worker pid data */ char pidFSuffix[13] = { 0 }; snprintf(pidFSuffix, sizeof(pidFSuffix), "%d.sancov", fuzzer->pid); /* Total BBs counter summarizes all DSOs */ uint64_t nBBs = 0; /* Iterate sancov dir for files generated against fuzzer pid */ snprintf(covFile, sizeof(covFile), "%s/%s", hfuzz->workDir, _HF_SANCOV_DIR); pSanCovDir = opendir(covFile); struct dirent *pDir = NULL; while ((pDir = readdir(pSanCovDir)) != NULL) { /* Parse files with worker's PID */ if (strstr(pDir->d_name, pidFSuffix)) { snprintf(covFile, sizeof(covFile), "%s/%s/%s", hfuzz->workDir, _HF_SANCOV_DIR, pDir->d_name); dataBuf = files_mapFile(covFile, &dataFileSz, &dataFd, false); if (dataBuf == NULL) { LOG_E("Couldn't open and map '%s' in R/O mode", covFile); goto bail; } if (dataFileSz < 8) { LOG_E("Coverage data file too short"); goto bail; } /* Check magic values & derive PC length */ uint64_t magic = util_getUINT64(dataBuf); if (magic == kMagic32) { is32bit = true; } else if (magic == kMagic64) { is32bit = false; } else { LOG_E("Invalid coverage data file"); goto bail; } pos += 8; /* * Avoid cost of size checks inside raw data read loop by defining the read function * & pivot size based on PC length. */ uint64_t(*pReadRawBBAddrFunc) (const uint8_t *) = NULL; uint8_t pivot = 0; if (is32bit) { pReadRawBBAddrFunc = &util_getUINT32; pivot = 4; } else { pReadRawBBAddrFunc = &util_getUINT64; pivot = 8; } while (pos < dataFileSz) { uint32_t bbAddr = pReadRawBBAddrFunc(dataBuf + pos); pos += pivot; if (bbAddr == 0x0) { continue; } nBBs++; } } } /* Successful parsing - update fuzzer worker counters */ fuzzer->sanCovCnts.hitBBCnt = nBBs; ret = true; bail: unlink(covFile); if (dataBuf) { munmap(dataBuf, dataFileSz); } if (dataFd != -1) { close(dataFd); } if (pSanCovDir) { closedir(pSanCovDir); } return ret; }