163 lines
4.7 KiB
Python
163 lines
4.7 KiB
Python
|
|
from pathlib import Path
|
|
import subprocess
|
|
import os
|
|
import glob, shutil
|
|
import sys
|
|
import random
|
|
|
|
|
|
def n_last_lines(path, n):
|
|
with open(path, 'r') as file:
|
|
lines = file.readlines()
|
|
return [line.strip() for line in lines][-n:]
|
|
|
|
|
|
def make_executable(path):
|
|
mode = os.stat(path).st_mode
|
|
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
|
os.chmod(path, mode)
|
|
|
|
|
|
def write_to_file(filename, insts, allow_fail=False):
|
|
with open(filename, 'w') as cfile:
|
|
print('#!/bin/bash', file=cfile)
|
|
if not allow_fail:
|
|
print('set -euo pipefail\n', file=cfile)
|
|
for inst in insts:
|
|
inst = inst.lstrip('// ')
|
|
print(inst, file=cfile)
|
|
make_executable(filename)
|
|
|
|
|
|
def combine_compile_instructions(compile_file, run_file, replay_file):
|
|
compile_cmds = []
|
|
run_cmds = []
|
|
repl_cmds = []
|
|
for root, dirs, files in os.walk('.'):
|
|
valids = [x for x in files if '.cpp' in x]
|
|
for name in valids:
|
|
path = os.path.join(root, name)
|
|
lines = n_last_lines(path, 8)
|
|
compile_cmds.extend(lines[-2:])
|
|
repl_cmds.extend([lines[-5]])
|
|
run_cmds.extend([lines[-8]])
|
|
|
|
write_to_file(compile_file, compile_cmds)
|
|
write_to_file(run_file, run_cmds, True)
|
|
write_to_file(replay_file, repl_cmds, True)
|
|
print('DONE!', compile_file, run_file, replay_file)
|
|
|
|
|
|
def combine_libfuzzer_commands():
|
|
compile_file = 'tst_compile.sh'
|
|
run_file = 'tst_run.sh'
|
|
repl_file = 'tst_repl.sh'
|
|
combine_compile_instructions(compile_file, run_file, repl_file)
|
|
|
|
|
|
def split_as_individuals():
|
|
with open('out_valid.cpp', 'r') as file:
|
|
lines = file.readlines()
|
|
lines = [line.rstrip() for line in lines]
|
|
includes = []
|
|
tc = []
|
|
tcs = []
|
|
tc_on = False
|
|
for line in lines:
|
|
if line.startswith('#include'):
|
|
includes.append(line)
|
|
elif tc_on:
|
|
if line.startswith('}'):
|
|
tc_on = False
|
|
tcs.append(tc)
|
|
else:
|
|
tc.append(line)
|
|
elif line.startswith('TEST('):
|
|
tc_on = True
|
|
tc = []
|
|
|
|
print(includes)
|
|
print(tcs)
|
|
|
|
|
|
def execute_cmd(cmd, store_output=False):
|
|
cwd = os.getcwd()
|
|
proc = subprocess.Popen(cmd, cwd=cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
if not store_output:
|
|
exit_code = proc.wait(30)
|
|
return []
|
|
|
|
output = []
|
|
with proc.stdout:
|
|
for line in iter(proc.stdout.readline, b''):
|
|
line = line.decode("utf-8")
|
|
line = line.rstrip()
|
|
output.append(line)
|
|
exit_code = proc.wait(30)
|
|
return output
|
|
|
|
|
|
CLEAN_CMD='find /home/robert/CLionProjects/SWTV-CXXFOOZZ/_test_real/re2 -name "*.gcda" -exec rm -f {} \;'
|
|
MEASURE_CMD='gcovr -r /home/robert/CLionProjects/SWTV-CXXFOOZZ/_test_real/re2 --branch -s /home/robert/CLionProjects/SWTV-CXXFOOZZ/_test_real/re2/build_libfuzzer/CMakeFiles/re2.dir/ --gcov-executable gcov_for_clang.sh'
|
|
|
|
|
|
def replay_all_drivers():
|
|
with open('tst_repl.sh', 'r') as file:
|
|
lines = file.readlines()
|
|
lines = [line.strip() for line in lines]
|
|
lines = [line for line in lines if line != '#!/bin/bash']
|
|
insts = []
|
|
for idx, line in enumerate(lines):
|
|
insts.append(CLEAN_CMD + ' &> /dev/null')
|
|
insts.append('timeout 60s ' + line + ' &> /dev/null')
|
|
insts.append(MEASURE_CMD + ' | tail -n2')
|
|
|
|
write_to_file('tst_repl_combined.sh', insts, True)
|
|
print('To use: ./tst_repl_combined.sh')
|
|
|
|
def replay_by_drivers(take, repeat):
|
|
with open('tst_repl.sh', 'r') as file:
|
|
lines = file.readlines()
|
|
lines = [line.strip() for line in lines]
|
|
lines = [line for line in lines if line != '#!/bin/bash']
|
|
|
|
insts = []
|
|
for _rep in range(repeat):
|
|
filename = 'tst_repl_' + str(_rep) + '.sh'
|
|
sampled = random.sample(lines, take)
|
|
sampled = ['timeout 60s ' + s for s in sampled]
|
|
write_to_file(filename, sampled, True)
|
|
|
|
insts.append(CLEAN_CMD + ' &> /dev/null')
|
|
insts.append('./' + filename + ' &> /dev/null')
|
|
insts.append(MEASURE_CMD + ' | tail -n2')
|
|
|
|
write_to_file('tst_repl_combined.sh', insts, True)
|
|
print('To use: ./tst_repl_combined.sh')
|
|
|
|
|
|
def usage():
|
|
print('To use: python3 batch_libfuzzer.py [gen|repl_all|repl X X]')
|
|
exit(0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
args = sys.argv
|
|
if len(args) < 2:
|
|
usage()
|
|
|
|
cmd = args[1]
|
|
if cmd == 'gen':
|
|
combine_libfuzzer_commands()
|
|
elif cmd == 'repl':
|
|
if len(args) < 4:
|
|
usage()
|
|
take = int(args[2])
|
|
repeat = int(args[3])
|
|
replay_by_drivers(take, repeat)
|
|
elif cmd == 'repl_all':
|
|
replay_all_drivers()
|
|
else:
|
|
usage()
|