xref: /aosp_15_r20/external/AFLplusplus/afl-cmin (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1*08b48e0bSAndroid Build Coastguard Worker#!/usr/bin/env sh
2*08b48e0bSAndroid Build Coastguard WorkerSYS=$(uname -s)
3*08b48e0bSAndroid Build Coastguard Workertest "$SYS" = "Darwin" && {
4*08b48e0bSAndroid Build Coastguard Worker  echo Error: afl-cmin does not work on Apple currently. please use afl-cmin.bash instead.
5*08b48e0bSAndroid Build Coastguard Worker  exit 1
6*08b48e0bSAndroid Build Coastguard Worker}
7*08b48e0bSAndroid Build Coastguard Workerexport AFL_QUIET=1
8*08b48e0bSAndroid Build Coastguard Workerexport ASAN_OPTIONS=detect_leaks=0
9*08b48e0bSAndroid Build Coastguard WorkerTHISPATH=`dirname ${0}`
10*08b48e0bSAndroid Build Coastguard Workerexport PATH="${THISPATH}:$PATH"
11*08b48e0bSAndroid Build Coastguard Workerawk -f - -- ${@+"$@"} <<'EOF'
12*08b48e0bSAndroid Build Coastguard Worker#!/usr/bin/awk -f
13*08b48e0bSAndroid Build Coastguard Worker# awk script to minimize a test corpus of input files
14*08b48e0bSAndroid Build Coastguard Worker#
15*08b48e0bSAndroid Build Coastguard Worker# based on afl-cmin bash script written by Michal Zalewski
16*08b48e0bSAndroid Build Coastguard Worker# rewritten by Heiko Eißfeldt (hexcoder-)
17*08b48e0bSAndroid Build Coastguard Worker# tested with:
18*08b48e0bSAndroid Build Coastguard Worker#   gnu awk (x86 Linux)
19*08b48e0bSAndroid Build Coastguard Worker#   bsd awk (x86 *BSD)
20*08b48e0bSAndroid Build Coastguard Worker#   mawk (arm32 raspbian)
21*08b48e0bSAndroid Build Coastguard Worker#
22*08b48e0bSAndroid Build Coastguard Worker# uses getopt.awk package from Arnold Robbins
23*08b48e0bSAndroid Build Coastguard Worker#
24*08b48e0bSAndroid Build Coastguard Worker# external tools used by this script:
25*08b48e0bSAndroid Build Coastguard Worker# test
26*08b48e0bSAndroid Build Coastguard Worker# grep
27*08b48e0bSAndroid Build Coastguard Worker# rm
28*08b48e0bSAndroid Build Coastguard Worker# mkdir
29*08b48e0bSAndroid Build Coastguard Worker# ln
30*08b48e0bSAndroid Build Coastguard Worker# cp
31*08b48e0bSAndroid Build Coastguard Worker# pwd
32*08b48e0bSAndroid Build Coastguard Worker# type
33*08b48e0bSAndroid Build Coastguard Worker# cd
34*08b48e0bSAndroid Build Coastguard Worker# find
35*08b48e0bSAndroid Build Coastguard Worker# stat
36*08b48e0bSAndroid Build Coastguard Worker# sort
37*08b48e0bSAndroid Build Coastguard Worker# cut
38*08b48e0bSAndroid Build Coastguard Worker# and afl-showmap from this project :-)
39*08b48e0bSAndroid Build Coastguard Worker
40*08b48e0bSAndroid Build Coastguard Worker# getopt.awk --- Do C library getopt(3) function in awk
41*08b48e0bSAndroid Build Coastguard Worker
42*08b48e0bSAndroid Build Coastguard Worker# External variables:
43*08b48e0bSAndroid Build Coastguard Worker#    Optind -- index in ARGV of first nonoption argument
44*08b48e0bSAndroid Build Coastguard Worker#    Optarg -- string value of argument to current option
45*08b48e0bSAndroid Build Coastguard Worker#    Opterr -- if nonzero, print our own diagnostic
46*08b48e0bSAndroid Build Coastguard Worker#    Optopt -- current option letter
47*08b48e0bSAndroid Build Coastguard Worker
48*08b48e0bSAndroid Build Coastguard Worker# Returns:
49*08b48e0bSAndroid Build Coastguard Worker#    -1     at end of options
50*08b48e0bSAndroid Build Coastguard Worker#    "?"    for unrecognized option
51*08b48e0bSAndroid Build Coastguard Worker#    <c>    a character representing the current option
52*08b48e0bSAndroid Build Coastguard Worker
53*08b48e0bSAndroid Build Coastguard Worker# Private Data:
54*08b48e0bSAndroid Build Coastguard Worker#    _opti  -- index in multiflag option, e.g., -abc
55*08b48e0bSAndroid Build Coastguard Worker
56*08b48e0bSAndroid Build Coastguard Workerfunction getopt(argc, argv, options,    thisopt, i)
57*08b48e0bSAndroid Build Coastguard Worker{
58*08b48e0bSAndroid Build Coastguard Worker    if (length(options) == 0)    # no options given
59*08b48e0bSAndroid Build Coastguard Worker        return -1
60*08b48e0bSAndroid Build Coastguard Worker
61*08b48e0bSAndroid Build Coastguard Worker    if (argv[Optind] == "--") {  # all done
62*08b48e0bSAndroid Build Coastguard Worker        Optind++
63*08b48e0bSAndroid Build Coastguard Worker        _opti = 0
64*08b48e0bSAndroid Build Coastguard Worker        return -1
65*08b48e0bSAndroid Build Coastguard Worker    } else if (argv[Optind] !~ /^-[^:\t ]/) {
66*08b48e0bSAndroid Build Coastguard Worker        _opti = 0
67*08b48e0bSAndroid Build Coastguard Worker        return -1
68*08b48e0bSAndroid Build Coastguard Worker    }
69*08b48e0bSAndroid Build Coastguard Worker    if (_opti == 0)
70*08b48e0bSAndroid Build Coastguard Worker        _opti = 2
71*08b48e0bSAndroid Build Coastguard Worker    thisopt = substr(argv[Optind], _opti, 1)
72*08b48e0bSAndroid Build Coastguard Worker    Optopt = thisopt
73*08b48e0bSAndroid Build Coastguard Worker    i = index(options, thisopt)
74*08b48e0bSAndroid Build Coastguard Worker    if (i == 0) {
75*08b48e0bSAndroid Build Coastguard Worker        if (Opterr)
76*08b48e0bSAndroid Build Coastguard Worker            printf("%c -- invalid option\n", thisopt) > "/dev/stderr"
77*08b48e0bSAndroid Build Coastguard Worker        if (_opti >= length(argv[Optind])) {
78*08b48e0bSAndroid Build Coastguard Worker            Optind++
79*08b48e0bSAndroid Build Coastguard Worker            _opti = 0
80*08b48e0bSAndroid Build Coastguard Worker        } else
81*08b48e0bSAndroid Build Coastguard Worker            _opti++
82*08b48e0bSAndroid Build Coastguard Worker        return "?"
83*08b48e0bSAndroid Build Coastguard Worker    }
84*08b48e0bSAndroid Build Coastguard Worker    if (substr(options, i + 1, 1) == ":") {
85*08b48e0bSAndroid Build Coastguard Worker        # get option argument
86*08b48e0bSAndroid Build Coastguard Worker        if (length(substr(argv[Optind], _opti + 1)) > 0)
87*08b48e0bSAndroid Build Coastguard Worker            Optarg = substr(argv[Optind], _opti + 1)
88*08b48e0bSAndroid Build Coastguard Worker        else
89*08b48e0bSAndroid Build Coastguard Worker            Optarg = argv[++Optind]
90*08b48e0bSAndroid Build Coastguard Worker        _opti = 0
91*08b48e0bSAndroid Build Coastguard Worker    } else
92*08b48e0bSAndroid Build Coastguard Worker        Optarg = ""
93*08b48e0bSAndroid Build Coastguard Worker    if (_opti == 0 || _opti >= length(argv[Optind])) {
94*08b48e0bSAndroid Build Coastguard Worker        Optind++
95*08b48e0bSAndroid Build Coastguard Worker        _opti = 0
96*08b48e0bSAndroid Build Coastguard Worker    } else
97*08b48e0bSAndroid Build Coastguard Worker        _opti++
98*08b48e0bSAndroid Build Coastguard Worker    return thisopt
99*08b48e0bSAndroid Build Coastguard Worker}
100*08b48e0bSAndroid Build Coastguard Worker
101*08b48e0bSAndroid Build Coastguard Workerfunction usage() {
102*08b48e0bSAndroid Build Coastguard Worker   print \
103*08b48e0bSAndroid Build Coastguard Worker"afl-cmin [ options ] -- /path/to/target_app [ ... ]\n" \
104*08b48e0bSAndroid Build Coastguard Worker"\n" \
105*08b48e0bSAndroid Build Coastguard Worker"Required parameters:\n" \
106*08b48e0bSAndroid Build Coastguard Worker"  -i dir        - input directory with starting corpus\n" \
107*08b48e0bSAndroid Build Coastguard Worker"  -o dir        - output directory for minimized files\n" \
108*08b48e0bSAndroid Build Coastguard Worker"\n" \
109*08b48e0bSAndroid Build Coastguard Worker"Execution control settings:\n" \
110*08b48e0bSAndroid Build Coastguard Worker"  -T tasks      - how many parallel tasks to run (default: 1, all=nproc)\n" \
111*08b48e0bSAndroid Build Coastguard Worker"  -f file       - location read by the fuzzed program (stdin)\n" \
112*08b48e0bSAndroid Build Coastguard Worker"  -m megs       - memory limit for child process ("mem_limit" MB)\n" \
113*08b48e0bSAndroid Build Coastguard Worker"  -t msec       - run time limit for child process (default: 5000)\n" \
114*08b48e0bSAndroid Build Coastguard Worker"  -O            - use binary-only instrumentation (FRIDA mode)\n" \
115*08b48e0bSAndroid Build Coastguard Worker"  -Q            - use binary-only instrumentation (QEMU mode)\n" \
116*08b48e0bSAndroid Build Coastguard Worker"  -U            - use unicorn-based instrumentation (unicorn mode)\n" \
117*08b48e0bSAndroid Build Coastguard Worker"  -X            - use Nyx mode\n" \
118*08b48e0bSAndroid Build Coastguard Worker"\n" \
119*08b48e0bSAndroid Build Coastguard Worker"Minimization settings:\n" \
120*08b48e0bSAndroid Build Coastguard Worker"  -A            - allow crashes and timeouts (not recommended)\n" \
121*08b48e0bSAndroid Build Coastguard Worker"  -C            - keep crashing inputs, reject everything else\n" \
122*08b48e0bSAndroid Build Coastguard Worker"  -e            - solve for edge coverage only, ignore hit counts\n" \
123*08b48e0bSAndroid Build Coastguard Worker"\n" \
124*08b48e0bSAndroid Build Coastguard Worker"For additional tips, please consult README.md\n" \
125*08b48e0bSAndroid Build Coastguard Worker"\n" \
126*08b48e0bSAndroid Build Coastguard Worker"Environment variables used:\n" \
127*08b48e0bSAndroid Build Coastguard Worker"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
128*08b48e0bSAndroid Build Coastguard Worker"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
129*08b48e0bSAndroid Build Coastguard Worker"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
130*08b48e0bSAndroid Build Coastguard Worker"AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \
131*08b48e0bSAndroid Build Coastguard Worker"AFL_FORK_SERVER_KILL_SIGNAL: Signal delivered to fork server processes on\n" \
132*08b48e0bSAndroid Build Coastguard Worker"   termination (default: SIGTERM). If this is not set and AFL_KILL_SIGNAL is\n" \
133*08b48e0bSAndroid Build Coastguard Worker"   set, this will be set to the same value as AFL_KILL_SIGNAL.\n" \
134*08b48e0bSAndroid Build Coastguard Worker"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" \
135*08b48e0bSAndroid Build Coastguard Worker"AFL_CMIN_ALLOW_ANY: write tuples for crashing inputs also\n" \
136*08b48e0bSAndroid Build Coastguard Worker"AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \
137*08b48e0bSAndroid Build Coastguard Worker"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
138*08b48e0bSAndroid Build Coastguard Worker      "printed to stdout\n" \
139*08b48e0bSAndroid Build Coastguard Worker"AFL_SKIP_BIN_CHECK: skip afl instrumentation checks for target binary\n"
140*08b48e0bSAndroid Build Coastguard Worker"AFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send)\n"
141*08b48e0bSAndroid Build Coastguard Worker"AFL_PYTHON_MODULE: custom mutator library (post_process and send)\n"
142*08b48e0bSAndroid Build Coastguard Worker   exit 1
143*08b48e0bSAndroid Build Coastguard Worker}
144*08b48e0bSAndroid Build Coastguard Worker
145*08b48e0bSAndroid Build Coastguard Workerfunction exists_and_is_executable(binarypath) {
146*08b48e0bSAndroid Build Coastguard Worker  return 0 == system("test -f "binarypath" -a -x "binarypath)
147*08b48e0bSAndroid Build Coastguard Worker}
148*08b48e0bSAndroid Build Coastguard Worker
149*08b48e0bSAndroid Build Coastguard WorkerBEGIN {
150*08b48e0bSAndroid Build Coastguard Worker  if (0 != system( "test -t 1")) {
151*08b48e0bSAndroid Build Coastguard Worker    redirected = 1
152*08b48e0bSAndroid Build Coastguard Worker  } else {
153*08b48e0bSAndroid Build Coastguard Worker    redirected = 0
154*08b48e0bSAndroid Build Coastguard Worker  }
155*08b48e0bSAndroid Build Coastguard Worker
156*08b48e0bSAndroid Build Coastguard Worker  print "corpus minimization tool for AFL++ (awk version)\n"
157*08b48e0bSAndroid Build Coastguard Worker
158*08b48e0bSAndroid Build Coastguard Worker  # defaults
159*08b48e0bSAndroid Build Coastguard Worker  extra_par = ""
160*08b48e0bSAndroid Build Coastguard Worker  AFL_CMIN_CRASHES_ONLY = ""
161*08b48e0bSAndroid Build Coastguard Worker  AFL_CMIN_ALLOW_ANY = ""
162*08b48e0bSAndroid Build Coastguard Worker
163*08b48e0bSAndroid Build Coastguard Worker  # process options
164*08b48e0bSAndroid Build Coastguard Worker  Opterr = 1    # default is to diagnose
165*08b48e0bSAndroid Build Coastguard Worker  Optind = 1    # skip ARGV[0]
166*08b48e0bSAndroid Build Coastguard Worker  while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXYT:?")) != -1) {
167*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "i") {
168*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
169*08b48e0bSAndroid Build Coastguard Worker      if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
170*08b48e0bSAndroid Build Coastguard Worker      in_dir = Optarg
171*08b48e0bSAndroid Build Coastguard Worker      continue
172*08b48e0bSAndroid Build Coastguard Worker    } else
173*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "T") {
174*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
175*08b48e0bSAndroid Build Coastguard Worker      if (threads) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
176*08b48e0bSAndroid Build Coastguard Worker      threads = Optarg
177*08b48e0bSAndroid Build Coastguard Worker      continue
178*08b48e0bSAndroid Build Coastguard Worker    } else
179*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "o") {
180*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
181*08b48e0bSAndroid Build Coastguard Worker      if (out_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
182*08b48e0bSAndroid Build Coastguard Worker      out_dir = Optarg
183*08b48e0bSAndroid Build Coastguard Worker      continue
184*08b48e0bSAndroid Build Coastguard Worker    } else
185*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "f") {
186*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
187*08b48e0bSAndroid Build Coastguard Worker      if (stdin_file) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
188*08b48e0bSAndroid Build Coastguard Worker      stdin_file = Optarg
189*08b48e0bSAndroid Build Coastguard Worker      continue
190*08b48e0bSAndroid Build Coastguard Worker    } else
191*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "m") {
192*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
193*08b48e0bSAndroid Build Coastguard Worker      if (mem_limit) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
194*08b48e0bSAndroid Build Coastguard Worker      mem_limit = Optarg
195*08b48e0bSAndroid Build Coastguard Worker      mem_limit_given = 1
196*08b48e0bSAndroid Build Coastguard Worker      continue
197*08b48e0bSAndroid Build Coastguard Worker    } else
198*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "t") {
199*08b48e0bSAndroid Build Coastguard Worker      if (!Optarg) usage()
200*08b48e0bSAndroid Build Coastguard Worker      if (timeout) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
201*08b48e0bSAndroid Build Coastguard Worker      timeout = Optarg
202*08b48e0bSAndroid Build Coastguard Worker      continue
203*08b48e0bSAndroid Build Coastguard Worker    } else
204*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "C") {
205*08b48e0bSAndroid Build Coastguard Worker      AFL_CMIN_CRASHES_ONLY = "AFL_CMIN_CRASHES_ONLY=1 "
206*08b48e0bSAndroid Build Coastguard Worker      continue
207*08b48e0bSAndroid Build Coastguard Worker    } else
208*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "A") {
209*08b48e0bSAndroid Build Coastguard Worker      AFL_CMIN_ALLOW_ANY = "AFL_CMIN_ALLOW_ANY=1 "
210*08b48e0bSAndroid Build Coastguard Worker      continue
211*08b48e0bSAndroid Build Coastguard Worker    } else
212*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "e") {
213*08b48e0bSAndroid Build Coastguard Worker      extra_par = extra_par " -e"
214*08b48e0bSAndroid Build Coastguard Worker      continue
215*08b48e0bSAndroid Build Coastguard Worker    } else
216*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "O") {
217*08b48e0bSAndroid Build Coastguard Worker      if (frida_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
218*08b48e0bSAndroid Build Coastguard Worker      extra_par = extra_par " -O"
219*08b48e0bSAndroid Build Coastguard Worker      frida_mode = 1
220*08b48e0bSAndroid Build Coastguard Worker      continue
221*08b48e0bSAndroid Build Coastguard Worker    } else
222*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "Q") {
223*08b48e0bSAndroid Build Coastguard Worker      if (qemu_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
224*08b48e0bSAndroid Build Coastguard Worker      extra_par = extra_par " -Q"
225*08b48e0bSAndroid Build Coastguard Worker      qemu_mode = 1
226*08b48e0bSAndroid Build Coastguard Worker      continue
227*08b48e0bSAndroid Build Coastguard Worker    } else
228*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "U") {
229*08b48e0bSAndroid Build Coastguard Worker      if (unicorn_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
230*08b48e0bSAndroid Build Coastguard Worker      extra_par = extra_par " -U"
231*08b48e0bSAndroid Build Coastguard Worker      unicorn_mode = 1
232*08b48e0bSAndroid Build Coastguard Worker      continue
233*08b48e0bSAndroid Build Coastguard Worker    } else
234*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "X" || _go_c == "Y") {
235*08b48e0bSAndroid Build Coastguard Worker      if (nyx_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
236*08b48e0bSAndroid Build Coastguard Worker      extra_par = extra_par " -X"
237*08b48e0bSAndroid Build Coastguard Worker      nyx_mode = 1
238*08b48e0bSAndroid Build Coastguard Worker      continue
239*08b48e0bSAndroid Build Coastguard Worker    } else
240*08b48e0bSAndroid Build Coastguard Worker    if (_go_c == "?") {
241*08b48e0bSAndroid Build Coastguard Worker      exit 1
242*08b48e0bSAndroid Build Coastguard Worker    } else
243*08b48e0bSAndroid Build Coastguard Worker      usage()
244*08b48e0bSAndroid Build Coastguard Worker  } # while options
245*08b48e0bSAndroid Build Coastguard Worker
246*08b48e0bSAndroid Build Coastguard Worker  if (!mem_limit) mem_limit = "none"
247*08b48e0bSAndroid Build Coastguard Worker  if (!timeout) timeout = "5000"
248*08b48e0bSAndroid Build Coastguard Worker
249*08b48e0bSAndroid Build Coastguard Worker  # get program args
250*08b48e0bSAndroid Build Coastguard Worker  i = 0
251*08b48e0bSAndroid Build Coastguard Worker  prog_args_string = ""
252*08b48e0bSAndroid Build Coastguard Worker  for (; Optind < ARGC; Optind++) {
253*08b48e0bSAndroid Build Coastguard Worker    prog_args[i++] = ARGV[Optind]
254*08b48e0bSAndroid Build Coastguard Worker    if (i > 1)
255*08b48e0bSAndroid Build Coastguard Worker      prog_args_string = prog_args_string" '"ARGV[Optind]"'"
256*08b48e0bSAndroid Build Coastguard Worker  }
257*08b48e0bSAndroid Build Coastguard Worker
258*08b48e0bSAndroid Build Coastguard Worker  # sanity checks
259*08b48e0bSAndroid Build Coastguard Worker  if (!prog_args[0] || !in_dir || !out_dir) usage()
260*08b48e0bSAndroid Build Coastguard Worker
261*08b48e0bSAndroid Build Coastguard Worker  target_bin = prog_args[0]
262*08b48e0bSAndroid Build Coastguard Worker
263*08b48e0bSAndroid Build Coastguard Worker  # Do a sanity check to discourage the use of /tmp, since we can't really
264*08b48e0bSAndroid Build Coastguard Worker  # handle this safely from an awk script.
265*08b48e0bSAndroid Build Coastguard Worker
266*08b48e0bSAndroid Build Coastguard Worker  if (!ENVIRON["AFL_ALLOW_TMP"]) {
267*08b48e0bSAndroid Build Coastguard Worker    dirlist[0] = in_dir
268*08b48e0bSAndroid Build Coastguard Worker    dirlist[1] = target_bin
269*08b48e0bSAndroid Build Coastguard Worker    dirlist[2] = out_dir
270*08b48e0bSAndroid Build Coastguard Worker    dirlist[3] = stdin_file
271*08b48e0bSAndroid Build Coastguard Worker    "pwd" | getline dirlist[4] # current directory
272*08b48e0bSAndroid Build Coastguard Worker    for (dirind in dirlist) {
273*08b48e0bSAndroid Build Coastguard Worker      dir = dirlist[dirind]
274*08b48e0bSAndroid Build Coastguard Worker      if (dir ~ /^(\/var)?\/tmp/) {
275*08b48e0bSAndroid Build Coastguard Worker        print "[-] Warning: do not use this script in /tmp or /var/tmp for security reasons." > "/dev/stderr"
276*08b48e0bSAndroid Build Coastguard Worker      }
277*08b48e0bSAndroid Build Coastguard Worker    }
278*08b48e0bSAndroid Build Coastguard Worker    delete dirlist
279*08b48e0bSAndroid Build Coastguard Worker  }
280*08b48e0bSAndroid Build Coastguard Worker
281*08b48e0bSAndroid Build Coastguard Worker  if (threads && stdin_file) {
282*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: -T and -f cannot be used together." > "/dev/stderr"
283*08b48e0bSAndroid Build Coastguard Worker    exit 1
284*08b48e0bSAndroid Build Coastguard Worker  }
285*08b48e0bSAndroid Build Coastguard Worker
286*08b48e0bSAndroid Build Coastguard Worker  if (!threads && !stdin_file && !nyx_mode) {
287*08b48e0bSAndroid Build Coastguard Worker    print "[*] Are you aware of the '-T all' parallelize option that improves the speed for large/slow corpuses?"
288*08b48e0bSAndroid Build Coastguard Worker  }
289*08b48e0bSAndroid Build Coastguard Worker
290*08b48e0bSAndroid Build Coastguard Worker  # If @@ is specified, but there's no -f, let's come up with a temporary input
291*08b48e0bSAndroid Build Coastguard Worker  # file name.
292*08b48e0bSAndroid Build Coastguard Worker
293*08b48e0bSAndroid Build Coastguard Worker  trace_dir = out_dir "/.traces"
294*08b48e0bSAndroid Build Coastguard Worker
295*08b48e0bSAndroid Build Coastguard Worker  if (!stdin_file) {
296*08b48e0bSAndroid Build Coastguard Worker    found_atat = 0
297*08b48e0bSAndroid Build Coastguard Worker    for (prog_args_ind in prog_args) {
298*08b48e0bSAndroid Build Coastguard Worker      if (match(prog_args[prog_args_ind], "@@") != 0) {
299*08b48e0bSAndroid Build Coastguard Worker        found_atat = 1
300*08b48e0bSAndroid Build Coastguard Worker        break
301*08b48e0bSAndroid Build Coastguard Worker      }
302*08b48e0bSAndroid Build Coastguard Worker    }
303*08b48e0bSAndroid Build Coastguard Worker    if (found_atat) {
304*08b48e0bSAndroid Build Coastguard Worker      stdin_file = trace_dir "/.cur_input"
305*08b48e0bSAndroid Build Coastguard Worker    }
306*08b48e0bSAndroid Build Coastguard Worker  }
307*08b48e0bSAndroid Build Coastguard Worker
308*08b48e0bSAndroid Build Coastguard Worker  # Check for obvious errors.
309*08b48e0bSAndroid Build Coastguard Worker
310*08b48e0bSAndroid Build Coastguard Worker  if (mem_limit && mem_limit != "none" && mem_limit < 5) {
311*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: dangerously low memory limit." > "/dev/stderr"
312*08b48e0bSAndroid Build Coastguard Worker    exit 1
313*08b48e0bSAndroid Build Coastguard Worker  }
314*08b48e0bSAndroid Build Coastguard Worker
315*08b48e0bSAndroid Build Coastguard Worker  if (timeout && timeout != "none" && timeout < 10) {
316*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: dangerously low timeout." > "/dev/stderr"
317*08b48e0bSAndroid Build Coastguard Worker    exit 1
318*08b48e0bSAndroid Build Coastguard Worker  }
319*08b48e0bSAndroid Build Coastguard Worker
320*08b48e0bSAndroid Build Coastguard Worker
321*08b48e0bSAndroid Build Coastguard Worker  if (!nyx_mode && target_bin && !exists_and_is_executable(target_bin)) {
322*08b48e0bSAndroid Build Coastguard Worker
323*08b48e0bSAndroid Build Coastguard Worker    cmd = "command -v "target_bin" 2>/dev/null"
324*08b48e0bSAndroid Build Coastguard Worker    cmd | getline tnew
325*08b48e0bSAndroid Build Coastguard Worker    close(cmd)
326*08b48e0bSAndroid Build Coastguard Worker    if (!tnew || !exists_and_is_executable(tnew)) {
327*08b48e0bSAndroid Build Coastguard Worker      print "[-] Error: binary '"target_bin"' not found or not executable." > "/dev/stderr"
328*08b48e0bSAndroid Build Coastguard Worker      exit 1
329*08b48e0bSAndroid Build Coastguard Worker    }
330*08b48e0bSAndroid Build Coastguard Worker    target_bin = tnew
331*08b48e0bSAndroid Build Coastguard Worker  }
332*08b48e0bSAndroid Build Coastguard Worker
333*08b48e0bSAndroid Build Coastguard Worker  if (0 == system ( "grep -aq AFL_DUMP_MAP_SIZE " target_bin )) {
334*08b48e0bSAndroid Build Coastguard Worker    echo "[!] Trying to obtain the map size of the target ..."
335*08b48e0bSAndroid Build Coastguard Worker    get_map_size = "AFL_DUMP_MAP_SIZE=1 " target_bin
336*08b48e0bSAndroid Build Coastguard Worker    get_map_size | getline mapsize
337*08b48e0bSAndroid Build Coastguard Worker    close(get_map_size)
338*08b48e0bSAndroid Build Coastguard Worker    if (mapsize && mapsize > 65535 && mapsize < 100000000) {
339*08b48e0bSAndroid Build Coastguard Worker      AFL_MAP_SIZE = "AFL_MAP_SIZE="mapsize" "
340*08b48e0bSAndroid Build Coastguard Worker      print "[+] Setting "AFL_MAP_SIZE
341*08b48e0bSAndroid Build Coastguard Worker    }
342*08b48e0bSAndroid Build Coastguard Worker  }
343*08b48e0bSAndroid Build Coastguard Worker
344*08b48e0bSAndroid Build Coastguard Worker  if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode && !nyx_mode) {
345*08b48e0bSAndroid Build Coastguard Worker    if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
346*08b48e0bSAndroid Build Coastguard Worker      print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
347*08b48e0bSAndroid Build Coastguard Worker      exit 1
348*08b48e0bSAndroid Build Coastguard Worker    }
349*08b48e0bSAndroid Build Coastguard Worker  }
350*08b48e0bSAndroid Build Coastguard Worker
351*08b48e0bSAndroid Build Coastguard Worker  if (0 != system( "test -d "in_dir )) {
352*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: directory '"in_dir"' not found." > "/dev/stderr"
353*08b48e0bSAndroid Build Coastguard Worker    exit 1
354*08b48e0bSAndroid Build Coastguard Worker  }
355*08b48e0bSAndroid Build Coastguard Worker
356*08b48e0bSAndroid Build Coastguard Worker  #if (0 == system( "test -d "in_dir"/default" )) {
357*08b48e0bSAndroid Build Coastguard Worker  #  in_dir = in_dir "/default"
358*08b48e0bSAndroid Build Coastguard Worker  #}
359*08b48e0bSAndroid Build Coastguard Worker  #
360*08b48e0bSAndroid Build Coastguard Worker  #if (0 == system( "test -d "in_dir"/queue" )) {
361*08b48e0bSAndroid Build Coastguard Worker  #  in_dir = in_dir "/queue"
362*08b48e0bSAndroid Build Coastguard Worker  #}
363*08b48e0bSAndroid Build Coastguard Worker
364*08b48e0bSAndroid Build Coastguard Worker  system("rm -rf "trace_dir" 2>/dev/null");
365*08b48e0bSAndroid Build Coastguard Worker  system("rm "out_dir"/id[:_]* 2>/dev/null")
366*08b48e0bSAndroid Build Coastguard Worker
367*08b48e0bSAndroid Build Coastguard Worker  cmd = "ls "out_dir"/* 2>/dev/null | wc -l"
368*08b48e0bSAndroid Build Coastguard Worker  cmd | getline noofentries
369*08b48e0bSAndroid Build Coastguard Worker  close(cmd)
370*08b48e0bSAndroid Build Coastguard Worker  if (0 == system( "test -d "out_dir" -a "noofentries" -gt 0" )) {
371*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: directory '"out_dir"' exists and is not empty - delete it first." > "/dev/stderr"
372*08b48e0bSAndroid Build Coastguard Worker    exit 1
373*08b48e0bSAndroid Build Coastguard Worker  }
374*08b48e0bSAndroid Build Coastguard Worker
375*08b48e0bSAndroid Build Coastguard Worker  if (threads) {
376*08b48e0bSAndroid Build Coastguard Worker    cmd = "nproc"
377*08b48e0bSAndroid Build Coastguard Worker    cmd | getline nproc
378*08b48e0bSAndroid Build Coastguard Worker    close(cmd)
379*08b48e0bSAndroid Build Coastguard Worker    if (threads == "all") {
380*08b48e0bSAndroid Build Coastguard Worker      threads = nproc
381*08b48e0bSAndroid Build Coastguard Worker    } else {
382*08b48e0bSAndroid Build Coastguard Worker      if (!(threads > 1 && threads <= nproc)) {
383*08b48e0bSAndroid Build Coastguard Worker        print "[-] Error: -T option must be between 1 and "nproc" or \"all\"." > "/dev/stderr"
384*08b48e0bSAndroid Build Coastguard Worker        exit 1
385*08b48e0bSAndroid Build Coastguard Worker      }
386*08b48e0bSAndroid Build Coastguard Worker    }
387*08b48e0bSAndroid Build Coastguard Worker  }
388*08b48e0bSAndroid Build Coastguard Worker
389*08b48e0bSAndroid Build Coastguard Worker  # Check for the more efficient way to copy files...
390*08b48e0bSAndroid Build Coastguard Worker  if (0 != system("mkdir -p -m 0700 "trace_dir)) {
391*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: Cannot create directory "trace_dir > "/dev/stderr"
392*08b48e0bSAndroid Build Coastguard Worker    exit 1
393*08b48e0bSAndroid Build Coastguard Worker  }
394*08b48e0bSAndroid Build Coastguard Worker
395*08b48e0bSAndroid Build Coastguard Worker  if (stdin_file) {
396*08b48e0bSAndroid Build Coastguard Worker    # truncate input file
397*08b48e0bSAndroid Build Coastguard Worker    printf "" > stdin_file
398*08b48e0bSAndroid Build Coastguard Worker    close(stdin_file)
399*08b48e0bSAndroid Build Coastguard Worker  }
400*08b48e0bSAndroid Build Coastguard Worker
401*08b48e0bSAndroid Build Coastguard Worker  # First we look in PATH
402*08b48e0bSAndroid Build Coastguard Worker  if (0 == system("command -v afl-showmap >/dev/null 2>&1")) {
403*08b48e0bSAndroid Build Coastguard Worker    cmd = "command -v afl-showmap 2>/dev/null"
404*08b48e0bSAndroid Build Coastguard Worker    cmd | getline showmap
405*08b48e0bSAndroid Build Coastguard Worker    close(cmd)
406*08b48e0bSAndroid Build Coastguard Worker  } else {
407*08b48e0bSAndroid Build Coastguard Worker    # then we look in the current directory
408*08b48e0bSAndroid Build Coastguard Worker    if (0 == system("test -x ./afl-showmap")) {
409*08b48e0bSAndroid Build Coastguard Worker      showmap = "./afl-showmap"
410*08b48e0bSAndroid Build Coastguard Worker    } else {
411*08b48e0bSAndroid Build Coastguard Worker      if (ENVIRON["AFL_PATH"]) {
412*08b48e0bSAndroid Build Coastguard Worker        showmap = ENVIRON["AFL_PATH"] "/afl-showmap"
413*08b48e0bSAndroid Build Coastguard Worker      }
414*08b48e0bSAndroid Build Coastguard Worker    }
415*08b48e0bSAndroid Build Coastguard Worker  }
416*08b48e0bSAndroid Build Coastguard Worker
417*08b48e0bSAndroid Build Coastguard Worker  if (!showmap || 0 != system("test -x "showmap )) {
418*08b48e0bSAndroid Build Coastguard Worker    print "[-] Error: can't find 'afl-showmap' - please set AFL_PATH." > "/dev/stderr"
419*08b48e0bSAndroid Build Coastguard Worker    exit 1
420*08b48e0bSAndroid Build Coastguard Worker  }
421*08b48e0bSAndroid Build Coastguard Worker
422*08b48e0bSAndroid Build Coastguard Worker  # get list of input filenames sorted by size
423*08b48e0bSAndroid Build Coastguard Worker  i = 0
424*08b48e0bSAndroid Build Coastguard Worker  # yuck, gnu stat is option incompatible to bsd stat
425*08b48e0bSAndroid Build Coastguard Worker  # we use a heuristic to differentiate between
426*08b48e0bSAndroid Build Coastguard Worker  # GNU stat and other stats
427*08b48e0bSAndroid Build Coastguard Worker  cmd = "stat --version 2>/dev/null"
428*08b48e0bSAndroid Build Coastguard Worker  cmd | getline statversion
429*08b48e0bSAndroid Build Coastguard Worker  close(cmd)
430*08b48e0bSAndroid Build Coastguard Worker  if (statversion ~ /GNU coreutils/ || statversion ~ /BusyBox/) {
431*08b48e0bSAndroid Build Coastguard Worker    stat_format = "-c '%s %n'" # GNU
432*08b48e0bSAndroid Build Coastguard Worker  } else {
433*08b48e0bSAndroid Build Coastguard Worker    stat_format = "-f '%z %N'" # *BSD, MacOS
434*08b48e0bSAndroid Build Coastguard Worker  }
435*08b48e0bSAndroid Build Coastguard Worker  cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'"
436*08b48e0bSAndroid Build Coastguard Worker  #cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r"
437*08b48e0bSAndroid Build Coastguard Worker  #cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r"
438*08b48e0bSAndroid Build Coastguard Worker  #cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"
439*08b48e0bSAndroid Build Coastguard Worker  while (cmdline | getline) {
440*08b48e0bSAndroid Build Coastguard Worker    sub(/^[0-9]+ (\.\/)?/,"",$0)
441*08b48e0bSAndroid Build Coastguard Worker    infilesSmallToBigFull[i] = $0
442*08b48e0bSAndroid Build Coastguard Worker    sub(/.*\//, "", $0)
443*08b48e0bSAndroid Build Coastguard Worker    infilesSmallToBig[i] = $0
444*08b48e0bSAndroid Build Coastguard Worker    infilesSmallToBigMap[infilesSmallToBig[i]] = infilesSmallToBigFull[i]
445*08b48e0bSAndroid Build Coastguard Worker    infilesSmallToBigFullMap[infilesSmallToBigFull[i]] = infilesSmallToBig[i]
446*08b48e0bSAndroid Build Coastguard Worker    i++
447*08b48e0bSAndroid Build Coastguard Worker  }
448*08b48e0bSAndroid Build Coastguard Worker  close(cmdline)
449*08b48e0bSAndroid Build Coastguard Worker  in_count = i
450*08b48e0bSAndroid Build Coastguard Worker
451*08b48e0bSAndroid Build Coastguard Worker  first_file = infilesSmallToBigFull[0]
452*08b48e0bSAndroid Build Coastguard Worker
453*08b48e0bSAndroid Build Coastguard Worker  #if (0 == system("test -d ""\""in_dir"/"first_file"\"")) {
454*08b48e0bSAndroid Build Coastguard Worker  #  print "[-] Error: The input directory is empty or contains subdirectories - please fix." > "/dev/stderr"
455*08b48e0bSAndroid Build Coastguard Worker  #  exit 1
456*08b48e0bSAndroid Build Coastguard Worker  #}
457*08b48e0bSAndroid Build Coastguard Worker
458*08b48e0bSAndroid Build Coastguard Worker  system(">\""in_dir"/.afl-cmin.test\"")
459*08b48e0bSAndroid Build Coastguard Worker  if (0 == system("ln \""in_dir"/.afl-cmin.test\" "trace_dir"/.link_test")) {
460*08b48e0bSAndroid Build Coastguard Worker    cp_tool = "ln"
461*08b48e0bSAndroid Build Coastguard Worker  } else {
462*08b48e0bSAndroid Build Coastguard Worker    cp_tool = "cp"
463*08b48e0bSAndroid Build Coastguard Worker  }
464*08b48e0bSAndroid Build Coastguard Worker  system("rm -f \""in_dir"/.afl-cmin.test\"")
465*08b48e0bSAndroid Build Coastguard Worker
466*08b48e0bSAndroid Build Coastguard Worker  if (!ENVIRON["AFL_SKIP_BIN_CHECK"]) {
467*08b48e0bSAndroid Build Coastguard Worker    # Make sure that we can actually get anything out of afl-showmap before we
468*08b48e0bSAndroid Build Coastguard Worker    # waste too much time.
469*08b48e0bSAndroid Build Coastguard Worker
470*08b48e0bSAndroid Build Coastguard Worker    print "[*] Testing the target binary..."
471*08b48e0bSAndroid Build Coastguard Worker
472*08b48e0bSAndroid Build Coastguard Worker    if (!stdin_file) {
473*08b48e0bSAndroid Build Coastguard Worker      system(AFL_MAP_SIZE "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -- \""target_bin"\" "prog_args_string" <\""in_dir"/"first_file"\"")
474*08b48e0bSAndroid Build Coastguard Worker    } else {
475*08b48e0bSAndroid Build Coastguard Worker      system("cp \""in_dir"/"first_file"\" "stdin_file)
476*08b48e0bSAndroid Build Coastguard Worker      system(AFL_MAP_SIZE "AFL_CMIN_ALLOW_ANY=1 "AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"/.run_test\" -Z "extra_par" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
477*08b48e0bSAndroid Build Coastguard Worker    }
478*08b48e0bSAndroid Build Coastguard Worker
479*08b48e0bSAndroid Build Coastguard Worker    first_count = 0
480*08b48e0bSAndroid Build Coastguard Worker
481*08b48e0bSAndroid Build Coastguard Worker    runtest = trace_dir"/.run_test"
482*08b48e0bSAndroid Build Coastguard Worker    while ((getline < runtest) > 0) {
483*08b48e0bSAndroid Build Coastguard Worker      ++first_count
484*08b48e0bSAndroid Build Coastguard Worker    }
485*08b48e0bSAndroid Build Coastguard Worker    close(runtest)
486*08b48e0bSAndroid Build Coastguard Worker
487*08b48e0bSAndroid Build Coastguard Worker    if (first_count) {
488*08b48e0bSAndroid Build Coastguard Worker      print "[+] OK, "first_count" tuples recorded."
489*08b48e0bSAndroid Build Coastguard Worker    } else {
490*08b48e0bSAndroid Build Coastguard Worker      print "[-] Error: no instrumentation output detected (perhaps crash or timeout)." > "/dev/stderr"
491*08b48e0bSAndroid Build Coastguard Worker      if (!ENVIRON["AFL_KEEP_TRACES"]) {
492*08b48e0bSAndroid Build Coastguard Worker        system("rm -rf "trace_dir" 2>/dev/null")
493*08b48e0bSAndroid Build Coastguard Worker      }
494*08b48e0bSAndroid Build Coastguard Worker      exit 1
495*08b48e0bSAndroid Build Coastguard Worker    }
496*08b48e0bSAndroid Build Coastguard Worker  }
497*08b48e0bSAndroid Build Coastguard Worker
498*08b48e0bSAndroid Build Coastguard Worker  if (in_count < threads) {
499*08b48e0bSAndroid Build Coastguard Worker    threads = in_count
500*08b48e0bSAndroid Build Coastguard Worker    print "[!] WARNING: less inputs than threads, reducing threads to "threads" and likely the overhead of threading makes things slower..."
501*08b48e0bSAndroid Build Coastguard Worker  }
502*08b48e0bSAndroid Build Coastguard Worker
503*08b48e0bSAndroid Build Coastguard Worker  # Let's roll!
504*08b48e0bSAndroid Build Coastguard Worker
505*08b48e0bSAndroid Build Coastguard Worker  #############################
506*08b48e0bSAndroid Build Coastguard Worker  # STEP 1: Collecting traces #
507*08b48e0bSAndroid Build Coastguard Worker  #############################
508*08b48e0bSAndroid Build Coastguard Worker
509*08b48e0bSAndroid Build Coastguard Worker  if (threads) {
510*08b48e0bSAndroid Build Coastguard Worker
511*08b48e0bSAndroid Build Coastguard Worker    inputsperfile = int(in_count / threads)
512*08b48e0bSAndroid Build Coastguard Worker    if (in_count % threads) {
513*08b48e0bSAndroid Build Coastguard Worker      inputsperfile++;
514*08b48e0bSAndroid Build Coastguard Worker    }
515*08b48e0bSAndroid Build Coastguard Worker
516*08b48e0bSAndroid Build Coastguard Worker    cnt = 0;
517*08b48e0bSAndroid Build Coastguard Worker    tmpfile=out_dir "/.filelist"
518*08b48e0bSAndroid Build Coastguard Worker    for (instance = 1; instance < threads; instance++) {
519*08b48e0bSAndroid Build Coastguard Worker      for (i = 0; i < inputsperfile; i++) {
520*08b48e0bSAndroid Build Coastguard Worker        print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."instance
521*08b48e0bSAndroid Build Coastguard Worker        cnt++
522*08b48e0bSAndroid Build Coastguard Worker      }
523*08b48e0bSAndroid Build Coastguard Worker    }
524*08b48e0bSAndroid Build Coastguard Worker    for (; cnt < in_count; cnt++) {
525*08b48e0bSAndroid Build Coastguard Worker      print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."threads
526*08b48e0bSAndroid Build Coastguard Worker    }
527*08b48e0bSAndroid Build Coastguard Worker
528*08b48e0bSAndroid Build Coastguard Worker  }
529*08b48e0bSAndroid Build Coastguard Worker
530*08b48e0bSAndroid Build Coastguard Worker  print "[*] Obtaining traces for "in_count" input files in '"in_dir"'."
531*08b48e0bSAndroid Build Coastguard Worker
532*08b48e0bSAndroid Build Coastguard Worker  cur = 0;
533*08b48e0bSAndroid Build Coastguard Worker
534*08b48e0bSAndroid Build Coastguard Worker  if (threads > 1) {
535*08b48e0bSAndroid Build Coastguard Worker
536*08b48e0bSAndroid Build Coastguard Worker    print "[*] Creating " threads " parallel tasks with about " inputsperfile " items each."
537*08b48e0bSAndroid Build Coastguard Worker    for (i = 1; i <= threads; i++) {
538*08b48e0bSAndroid Build Coastguard Worker
539*08b48e0bSAndroid Build Coastguard Worker      if (!stdin_file) {
540*08b48e0bSAndroid Build Coastguard Worker#        print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &"
541*08b48e0bSAndroid Build Coastguard Worker        retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &")
542*08b48e0bSAndroid Build Coastguard Worker      } else {
543*08b48e0bSAndroid Build Coastguard Worker        stdin_file=tmpfile"."i".stdin"
544*08b48e0bSAndroid Build Coastguard Worker#        print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null; > "tmpfile"."i".done ; } &"
545*08b48e0bSAndroid Build Coastguard Worker        retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null; > "tmpfile"."i".done ; } &")
546*08b48e0bSAndroid Build Coastguard Worker      }
547*08b48e0bSAndroid Build Coastguard Worker    }
548*08b48e0bSAndroid Build Coastguard Worker    print "[*] Waiting for parallel tasks to complete ..."
549*08b48e0bSAndroid Build Coastguard Worker    # wait for all processes to finish
550*08b48e0bSAndroid Build Coastguard Worker    ok=0
551*08b48e0bSAndroid Build Coastguard Worker    while (ok < threads) {
552*08b48e0bSAndroid Build Coastguard Worker      ok=0
553*08b48e0bSAndroid Build Coastguard Worker      for (i = 1; i <= threads; i++) {
554*08b48e0bSAndroid Build Coastguard Worker        if (system("test -f "tmpfile"."i".done") == 0) {
555*08b48e0bSAndroid Build Coastguard Worker          ok++
556*08b48e0bSAndroid Build Coastguard Worker        }
557*08b48e0bSAndroid Build Coastguard Worker      }
558*08b48e0bSAndroid Build Coastguard Worker    }
559*08b48e0bSAndroid Build Coastguard Worker    print "[*] Done!"
560*08b48e0bSAndroid Build Coastguard Worker    system("rm -f "tmpfile"*")
561*08b48e0bSAndroid Build Coastguard Worker  } else {
562*08b48e0bSAndroid Build Coastguard Worker    if (!stdin_file) {
563*08b48e0bSAndroid Build Coastguard Worker      print "    Processing "in_count" files (forkserver mode)..."
564*08b48e0bSAndroid Build Coastguard Worker#      print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
565*08b48e0bSAndroid Build Coastguard Worker      retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string)
566*08b48e0bSAndroid Build Coastguard Worker    } else {
567*08b48e0bSAndroid Build Coastguard Worker      print "    Processing "in_count" files (forkserver mode)..."
568*08b48e0bSAndroid Build Coastguard Worker#    print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null"
569*08b48e0bSAndroid Build Coastguard Worker      retval = system(AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null")
570*08b48e0bSAndroid Build Coastguard Worker    }
571*08b48e0bSAndroid Build Coastguard Worker
572*08b48e0bSAndroid Build Coastguard Worker    if (retval && (!AFL_CMIN_CRASHES_ONLY && !AFL_CMIN_ALLOW_ANY)) {
573*08b48e0bSAndroid Build Coastguard Worker      print "[!] Exit code "retval" != 0 received from afl-showmap (this means a crashing or timeout input is likely present), terminating..."
574*08b48e0bSAndroid Build Coastguard Worker
575*08b48e0bSAndroid Build Coastguard Worker      if (!ENVIRON["AFL_KEEP_TRACES"]) {
576*08b48e0bSAndroid Build Coastguard Worker        system("rm -rf "trace_dir" 2>/dev/null")
577*08b48e0bSAndroid Build Coastguard Worker        system("rmdir "out_dir)
578*08b48e0bSAndroid Build Coastguard Worker      }
579*08b48e0bSAndroid Build Coastguard Worker      exit retval
580*08b48e0bSAndroid Build Coastguard Worker    }
581*08b48e0bSAndroid Build Coastguard Worker
582*08b48e0bSAndroid Build Coastguard Worker  }
583*08b48e0bSAndroid Build Coastguard Worker
584*08b48e0bSAndroid Build Coastguard Worker  #######################################################
585*08b48e0bSAndroid Build Coastguard Worker  # STEP 2: register smallest input file for each tuple #
586*08b48e0bSAndroid Build Coastguard Worker  # STEP 3: copy that file (at most once)               #
587*08b48e0bSAndroid Build Coastguard Worker  #######################################################
588*08b48e0bSAndroid Build Coastguard Worker
589*08b48e0bSAndroid Build Coastguard Worker  print "[*] Processing traces for input files in '"in_dir"'."
590*08b48e0bSAndroid Build Coastguard Worker
591*08b48e0bSAndroid Build Coastguard Worker  cur = 0
592*08b48e0bSAndroid Build Coastguard Worker  out_count = 0
593*08b48e0bSAndroid Build Coastguard Worker  tuple_count = 0
594*08b48e0bSAndroid Build Coastguard Worker
595*08b48e0bSAndroid Build Coastguard Worker  # from rare to frequent new tuples
596*08b48e0bSAndroid Build Coastguard Worker  # get the best (smallest) file for it
597*08b48e0bSAndroid Build Coastguard Worker  # and copy it
598*08b48e0bSAndroid Build Coastguard Worker  while (cur < in_count) {
599*08b48e0bSAndroid Build Coastguard Worker    fn = infilesSmallToBig[cur]
600*08b48e0bSAndroid Build Coastguard Worker    ++cur
601*08b48e0bSAndroid Build Coastguard Worker    if (redirected == 0) { printf "\r    Processing file "cur"/"in_count }
602*08b48e0bSAndroid Build Coastguard Worker    else { print "    Processing file "cur"/"in_count }
603*08b48e0bSAndroid Build Coastguard Worker    # create path for the trace file from afl-showmap
604*08b48e0bSAndroid Build Coastguard Worker    tracefile_path = trace_dir"/"fn
605*08b48e0bSAndroid Build Coastguard Worker    # ensure the file size is not zero
606*08b48e0bSAndroid Build Coastguard Worker    cmd = "du -b "tracefile_path
607*08b48e0bSAndroid Build Coastguard Worker    "ls -l "tracefile_path
608*08b48e0bSAndroid Build Coastguard Worker    cmd | getline output
609*08b48e0bSAndroid Build Coastguard Worker    close(cmd)
610*08b48e0bSAndroid Build Coastguard Worker    split(output, result, "\t")
611*08b48e0bSAndroid Build Coastguard Worker    if (result[1] == 0) {
612*08b48e0bSAndroid Build Coastguard Worker      print "[!] WARNING: file "fn" is crashing the target, ignoring..."
613*08b48e0bSAndroid Build Coastguard Worker    }
614*08b48e0bSAndroid Build Coastguard Worker    # gather all keys, and count them
615*08b48e0bSAndroid Build Coastguard Worker    while ((getline line < tracefile_path) > 0) {
616*08b48e0bSAndroid Build Coastguard Worker        key = line
617*08b48e0bSAndroid Build Coastguard Worker        if (!(key in key_count)) {
618*08b48e0bSAndroid Build Coastguard Worker          ++tuple_count
619*08b48e0bSAndroid Build Coastguard Worker        }
620*08b48e0bSAndroid Build Coastguard Worker        ++key_count[key]
621*08b48e0bSAndroid Build Coastguard Worker        if (! (key in best_file)) {
622*08b48e0bSAndroid Build Coastguard Worker            # this is the best file for this key
623*08b48e0bSAndroid Build Coastguard Worker            best_file[key] = fn
624*08b48e0bSAndroid Build Coastguard Worker#printf "BEST_FILE[%d]=\"%s\"\n",key,fn | "sort -t'[' -k2 > "trace_dir"/.candidate_script"
625*08b48e0bSAndroid Build Coastguard Worker        }
626*08b48e0bSAndroid Build Coastguard Worker#printf "%d %s\n",key,fn > trace_dir"/.candidate_list"
627*08b48e0bSAndroid Build Coastguard Worker    }
628*08b48e0bSAndroid Build Coastguard Worker    close(tracefile_path)
629*08b48e0bSAndroid Build Coastguard Worker  }
630*08b48e0bSAndroid Build Coastguard Worker  print ""
631*08b48e0bSAndroid Build Coastguard Worker
632*08b48e0bSAndroid Build Coastguard Worker  # sort keys
633*08b48e0bSAndroid Build Coastguard Worker  sortedKeys = trace_dir"/.all_uniq"
634*08b48e0bSAndroid Build Coastguard Worker  sortKeysCmd = "sort -k1n > "sortedKeys
635*08b48e0bSAndroid Build Coastguard Worker  for (key in key_count) {
636*08b48e0bSAndroid Build Coastguard Worker     printf "%7d %s\n",key_count[key],key | sortKeysCmd
637*08b48e0bSAndroid Build Coastguard Worker  }
638*08b48e0bSAndroid Build Coastguard Worker  close(sortKeysCmd)
639*08b48e0bSAndroid Build Coastguard Worker
640*08b48e0bSAndroid Build Coastguard Worker  # iterate over keys from rare to frequent and
641*08b48e0bSAndroid Build Coastguard Worker  # copy best file
642*08b48e0bSAndroid Build Coastguard Worker  while ((getline < sortedKeys) > 0) {
643*08b48e0bSAndroid Build Coastguard Worker
644*08b48e0bSAndroid Build Coastguard Worker    # split
645*08b48e0bSAndroid Build Coastguard Worker    nrFields = split($0, field, / +/)
646*08b48e0bSAndroid Build Coastguard Worker#print nrFields" Felder: '"field[0]"',  '"field[1]"',  '"field[2]"',  '"field[3]"'"
647*08b48e0bSAndroid Build Coastguard Worker    key = field[nrFields]
648*08b48e0bSAndroid Build Coastguard Worker
649*08b48e0bSAndroid Build Coastguard Worker    ++tcnt;
650*08b48e0bSAndroid Build Coastguard Worker    if (redirected == 0) { printf "\r    Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
651*08b48e0bSAndroid Build Coastguard Worker    else { print "    Processing tuple "tcnt"/"tuple_count" with count "key_count[key]"..." }
652*08b48e0bSAndroid Build Coastguard Worker
653*08b48e0bSAndroid Build Coastguard Worker    if (key in keyAlreadyKnown) {
654*08b48e0bSAndroid Build Coastguard Worker      continue
655*08b48e0bSAndroid Build Coastguard Worker    }
656*08b48e0bSAndroid Build Coastguard Worker
657*08b48e0bSAndroid Build Coastguard Worker    fn = best_file[key]
658*08b48e0bSAndroid Build Coastguard Worker    # gather all tuples from the best file for this key
659*08b48e0bSAndroid Build Coastguard Worker    tracedfn = trace_dir"/"fn
660*08b48e0bSAndroid Build Coastguard Worker    while ((getline < tracedfn) > 0) {
661*08b48e0bSAndroid Build Coastguard Worker      keyAlreadyKnown[$0] = ""
662*08b48e0bSAndroid Build Coastguard Worker    }
663*08b48e0bSAndroid Build Coastguard Worker    close(tracedfn)
664*08b48e0bSAndroid Build Coastguard Worker
665*08b48e0bSAndroid Build Coastguard Worker    # copy file unless already done
666*08b48e0bSAndroid Build Coastguard Worker    if (! (fn in file_already_copied)) {
667*08b48e0bSAndroid Build Coastguard Worker      realfile = infilesSmallToBigMap[fn]
668*08b48e0bSAndroid Build Coastguard Worker      system(cp_tool" \""in_dir"/"realfile"\" \""out_dir"/"fn"\"")
669*08b48e0bSAndroid Build Coastguard Worker      file_already_copied[fn] = ""
670*08b48e0bSAndroid Build Coastguard Worker      ++out_count
671*08b48e0bSAndroid Build Coastguard Worker      #printf "tuple nr %d (%d cnt=%d) -> %s\n",tcnt,key,key_count[key],fn > trace_dir"/.log"
672*08b48e0bSAndroid Build Coastguard Worker    }
673*08b48e0bSAndroid Build Coastguard Worker  }
674*08b48e0bSAndroid Build Coastguard Worker  close(sortedKeys)
675*08b48e0bSAndroid Build Coastguard Worker  print ""
676*08b48e0bSAndroid Build Coastguard Worker  print "[+] Found "tuple_count" unique tuples across "in_count" files."
677*08b48e0bSAndroid Build Coastguard Worker
678*08b48e0bSAndroid Build Coastguard Worker  if (out_count == 1) {
679*08b48e0bSAndroid Build Coastguard Worker    print "[!] WARNING: All test cases had the same traces, check syntax!"
680*08b48e0bSAndroid Build Coastguard Worker  }
681*08b48e0bSAndroid Build Coastguard Worker  print "[+] Narrowed down to "out_count" files, saved in '"out_dir"'."
682*08b48e0bSAndroid Build Coastguard Worker
683*08b48e0bSAndroid Build Coastguard Worker  if (!ENVIRON["AFL_KEEP_TRACES"]) {
684*08b48e0bSAndroid Build Coastguard Worker    system("rm -rf "trace_dir" 2>/dev/null")
685*08b48e0bSAndroid Build Coastguard Worker  }
686*08b48e0bSAndroid Build Coastguard Worker
687*08b48e0bSAndroid Build Coastguard Worker  exit 0
688*08b48e0bSAndroid Build Coastguard Worker}
689*08b48e0bSAndroid Build Coastguard WorkerEOF
690