-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
151 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
FD_HAS_MAIN:=0 | ||
CPPFLAGS+=-fno-omit-frame-pointer | ||
FD_HAS_FUZZ:=1 | ||
|
||
CPPFLAGS+=-DFD_HAS_FUZZ=1 | ||
CPPFLAGS+=-fno-omit-frame-pointer | ||
CPPFLAGS+=-fsanitize=fuzzer-no-link | ||
|
||
LDFLAGS+=-fsanitize=fuzzer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# run this script from the top of the repository | ||
|
||
from collections import defaultdict | ||
import functools | ||
import os | ||
import subprocess | ||
import sys | ||
|
||
def main(lcov_files): | ||
canaries = find_canaries() | ||
|
||
# turn canaries into map of (file_name -> {linum, ...}) | ||
def add(a, c): | ||
a[c.file].add(c.linum) | ||
return a | ||
files_to_lines = functools.reduce(add, canaries, defaultdict(set)) | ||
|
||
print(f"canaries found in source ({len(canaries)}):") | ||
for entry in files_to_lines.items(): | ||
print(f"\t{entry}") | ||
|
||
for lcov_path in lcov_files: | ||
files_to_lines = eliminate_canaries_with_lcov("./build/combi-cov/cov.lcov", files_to_lines) | ||
|
||
live_canaries = files_to_lines | ||
|
||
# check for canary canary - if absent, this tool has failed. | ||
if len(live_canaries["src/util/fuzz/fd_fuzz_canary_canary.c"]) != 1: | ||
print("the canary in fd_fuzz_canary_canary.c hasn't been found as uncovered - the tool is faulty", file=sys.stderr) | ||
os.exit(1) | ||
|
||
# remove the canary canary from the the findings | ||
del live_canaries["src/util/fuzz/fd_fuzz_canary_canary.c"] | ||
|
||
live_canaries = list(filter(lambda item: len(item[1]) != 0, live_canaries.items())) | ||
|
||
if not live_canaries: | ||
print("no uncovered canaries") | ||
|
||
else: | ||
for (canary_file, linums) in live_canaries: | ||
for linum in linums: | ||
print(f"::warning file={canary_file},line={linum}::\"Canary not yet covered by fuzzing\"") | ||
|
||
|
||
class Canary: | ||
def __init__(self, file, linum): | ||
self.file = file | ||
self.linum = linum | ||
|
||
def find_canaries(): | ||
# define the command to be executed | ||
cmd = ["grep", "-Hn", "-r", "--exclude=fd_fuzz.h", "FD_FUZZ_MUST_BE_COVERED", "src/"] | ||
try: | ||
# execute the command | ||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, text=True) | ||
|
||
# split the output into an array, one element per line | ||
output_lines = result.stdout.strip().split('\n') | ||
|
||
output_tokens = [] | ||
for line in output_lines: | ||
raw_canary = line.split(":", 2) | ||
output_tokens.append(Canary(raw_canary[0], raw_canary[1])) | ||
|
||
return output_tokens | ||
|
||
except subprocess.CalledProcessError as e: | ||
# Handle errors such as directory not found or grep command failure | ||
return ["Error: " + str(e)] | ||
|
||
# eliminate_canaries_with_lcov reads an lcov file at the specified path | ||
# and returns all of the canaries that were not covered | ||
def eliminate_canaries_with_lcov(path_to_lcov, canaries): | ||
cwd = os.getcwd() | ||
with open(path_to_lcov) as lcov: | ||
|
||
# loop state | ||
node_of_interest = None | ||
|
||
while True: # go over every line in the lcov | ||
line = lcov.readline() | ||
if line == "": | ||
break | ||
|
||
if line.startswith("SF:"): # new source file context: track node if applicable | ||
source_path = line.removeprefix(f"SF:{cwd}/").strip() # make path relative | ||
node_of_interest = canaries.get(source_path, None) | ||
|
||
elif line.startswith("end_of_context"): | ||
node_of_interest = None | ||
|
||
elif line.startswith("DA:"): | ||
if node_of_interest is not None: | ||
linum, _ = line.removeprefix("DA:").split(",", 1) | ||
node_of_interest.discard(linum) | ||
|
||
return canaries | ||
|
||
|
||
|
||
|
||
|
||
if __name__ == '__main__': | ||
main(sys.argv[1:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef HEADER_fd_src_util_fuzz_fd_fuzz_h | ||
#define HEADER_fd_src_util_fuzz_fd_fuzz_h | ||
|
||
#if FD_HAS_FUZZ | ||
#define FD_FUZZ_MUST_BE_COVERED ((void) 0) | ||
#else | ||
#define FD_FUZZ_MUST_BE_COVERED | ||
#endif | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* This files contains a canary that is expected to be found by the canary finder. | ||
If the script fails to find this canary, it will consider this a failure. */ | ||
|
||
#include "fd_fuzz.h" | ||
|
||
static void | ||
do_not_call_me( void ) { | ||
FD_FUZZ_MUST_BE_COVERED; | ||
} |