xref: /aosp_15_r20/external/AFLplusplus/afl-cmin.bash (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1*08b48e0bSAndroid Build Coastguard Worker#!/usr/bin/env bash
2*08b48e0bSAndroid Build Coastguard Worker#
3*08b48e0bSAndroid Build Coastguard Worker# american fuzzy lop++ - corpus minimization tool
4*08b48e0bSAndroid Build Coastguard Worker# ---------------------------------------------
5*08b48e0bSAndroid Build Coastguard Worker#
6*08b48e0bSAndroid Build Coastguard Worker# Originally written by Michal Zalewski
7*08b48e0bSAndroid Build Coastguard Worker#
8*08b48e0bSAndroid Build Coastguard Worker# Copyright 2014, 2015 Google Inc. All rights reserved.
9*08b48e0bSAndroid Build Coastguard Worker#
10*08b48e0bSAndroid Build Coastguard Worker# Copyright 2019-2024 AFLplusplus
11*08b48e0bSAndroid Build Coastguard Worker#
12*08b48e0bSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
13*08b48e0bSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
14*08b48e0bSAndroid Build Coastguard Worker# You may obtain a copy of the License at:
15*08b48e0bSAndroid Build Coastguard Worker#
16*08b48e0bSAndroid Build Coastguard Worker#   https://www.apache.org/licenses/LICENSE-2.0
17*08b48e0bSAndroid Build Coastguard Worker#
18*08b48e0bSAndroid Build Coastguard Worker# This tool tries to find the smallest subset of files in the input directory
19*08b48e0bSAndroid Build Coastguard Worker# that still trigger the full range of instrumentation data points seen in
20*08b48e0bSAndroid Build Coastguard Worker# the starting corpus. This has two uses:
21*08b48e0bSAndroid Build Coastguard Worker#
22*08b48e0bSAndroid Build Coastguard Worker#   - Screening large corpora of input files before using them as a seed for
23*08b48e0bSAndroid Build Coastguard Worker#     afl-fuzz. The tool will remove functionally redundant files and likely
24*08b48e0bSAndroid Build Coastguard Worker#     leave you with a much smaller set.
25*08b48e0bSAndroid Build Coastguard Worker#
26*08b48e0bSAndroid Build Coastguard Worker#     (In this case, you probably also want to consider running afl-tmin on
27*08b48e0bSAndroid Build Coastguard Worker#     the individual files later on to reduce their size.)
28*08b48e0bSAndroid Build Coastguard Worker#
29*08b48e0bSAndroid Build Coastguard Worker#   - Minimizing the corpus generated organically by afl-fuzz, perhaps when
30*08b48e0bSAndroid Build Coastguard Worker#     planning to feed it to more resource-intensive tools. The tool achieves
31*08b48e0bSAndroid Build Coastguard Worker#     this by removing all entries that used to trigger unique behaviors in the
32*08b48e0bSAndroid Build Coastguard Worker#     past, but have been made obsolete by later finds.
33*08b48e0bSAndroid Build Coastguard Worker#
34*08b48e0bSAndroid Build Coastguard Worker# Note that the tool doesn't modify the files themselves. For that, you want
35*08b48e0bSAndroid Build Coastguard Worker# afl-tmin.
36*08b48e0bSAndroid Build Coastguard Worker#
37*08b48e0bSAndroid Build Coastguard Worker# This script must use bash because other shells may have hardcoded limits on
38*08b48e0bSAndroid Build Coastguard Worker# array sizes.
39*08b48e0bSAndroid Build Coastguard Worker#
40*08b48e0bSAndroid Build Coastguard Worker
41*08b48e0bSAndroid Build Coastguard Workerecho "corpus minimization tool for afl-fuzz"
42*08b48e0bSAndroid Build Coastguard Workerecho
43*08b48e0bSAndroid Build Coastguard Worker
44*08b48e0bSAndroid Build Coastguard Worker#########
45*08b48e0bSAndroid Build Coastguard Worker# SETUP #
46*08b48e0bSAndroid Build Coastguard Worker#########
47*08b48e0bSAndroid Build Coastguard Worker
48*08b48e0bSAndroid Build Coastguard Worker# Process command-line options...
49*08b48e0bSAndroid Build Coastguard Worker
50*08b48e0bSAndroid Build Coastguard WorkerMEM_LIMIT=none
51*08b48e0bSAndroid Build Coastguard WorkerTIMEOUT=5000
52*08b48e0bSAndroid Build Coastguard Worker
53*08b48e0bSAndroid Build Coastguard Workerunset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN F_ARG \
54*08b48e0bSAndroid Build Coastguard Worker  AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE T_ARG
55*08b48e0bSAndroid Build Coastguard Worker
56*08b48e0bSAndroid Build Coastguard Workerexport AFL_QUIET=1
57*08b48e0bSAndroid Build Coastguard Worker
58*08b48e0bSAndroid Build Coastguard Workerwhile getopts "+i:o:f:m:t:T:eOQUAChXY" opt; do
59*08b48e0bSAndroid Build Coastguard Worker
60*08b48e0bSAndroid Build Coastguard Worker  case "$opt" in
61*08b48e0bSAndroid Build Coastguard Worker
62*08b48e0bSAndroid Build Coastguard Worker    "h")
63*08b48e0bSAndroid Build Coastguard Worker	;;
64*08b48e0bSAndroid Build Coastguard Worker
65*08b48e0bSAndroid Build Coastguard Worker    "i")
66*08b48e0bSAndroid Build Coastguard Worker         IN_DIR="$OPTARG"
67*08b48e0bSAndroid Build Coastguard Worker         ;;
68*08b48e0bSAndroid Build Coastguard Worker
69*08b48e0bSAndroid Build Coastguard Worker    "o")
70*08b48e0bSAndroid Build Coastguard Worker         OUT_DIR="$OPTARG"
71*08b48e0bSAndroid Build Coastguard Worker         ;;
72*08b48e0bSAndroid Build Coastguard Worker    "f")
73*08b48e0bSAndroid Build Coastguard Worker         STDIN_FILE="$OPTARG"
74*08b48e0bSAndroid Build Coastguard Worker         F_ARG=1
75*08b48e0bSAndroid Build Coastguard Worker         ;;
76*08b48e0bSAndroid Build Coastguard Worker    "m")
77*08b48e0bSAndroid Build Coastguard Worker         MEM_LIMIT="$OPTARG"
78*08b48e0bSAndroid Build Coastguard Worker         MEM_LIMIT_GIVEN=1
79*08b48e0bSAndroid Build Coastguard Worker         ;;
80*08b48e0bSAndroid Build Coastguard Worker    "t")
81*08b48e0bSAndroid Build Coastguard Worker         TIMEOUT="$OPTARG"
82*08b48e0bSAndroid Build Coastguard Worker         ;;
83*08b48e0bSAndroid Build Coastguard Worker    "e")
84*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -e"
85*08b48e0bSAndroid Build Coastguard Worker         ;;
86*08b48e0bSAndroid Build Coastguard Worker    "A")
87*08b48e0bSAndroid Build Coastguard Worker         export AFL_CMIN_ALLOW_ANY=1
88*08b48e0bSAndroid Build Coastguard Worker         ;;
89*08b48e0bSAndroid Build Coastguard Worker    "C")
90*08b48e0bSAndroid Build Coastguard Worker         export AFL_CMIN_CRASHES_ONLY=1
91*08b48e0bSAndroid Build Coastguard Worker         ;;
92*08b48e0bSAndroid Build Coastguard Worker    "O")
93*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -O"
94*08b48e0bSAndroid Build Coastguard Worker         FRIDA_MODE=1
95*08b48e0bSAndroid Build Coastguard Worker         ;;
96*08b48e0bSAndroid Build Coastguard Worker    "Q")
97*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -Q"
98*08b48e0bSAndroid Build Coastguard Worker         QEMU_MODE=1
99*08b48e0bSAndroid Build Coastguard Worker         ;;
100*08b48e0bSAndroid Build Coastguard Worker    "Y")
101*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -X"
102*08b48e0bSAndroid Build Coastguard Worker         NYX_MODE=1
103*08b48e0bSAndroid Build Coastguard Worker         ;;
104*08b48e0bSAndroid Build Coastguard Worker    "X")
105*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -X"
106*08b48e0bSAndroid Build Coastguard Worker         NYX_MODE=1
107*08b48e0bSAndroid Build Coastguard Worker         ;;
108*08b48e0bSAndroid Build Coastguard Worker    "U")
109*08b48e0bSAndroid Build Coastguard Worker         EXTRA_PAR="$EXTRA_PAR -U"
110*08b48e0bSAndroid Build Coastguard Worker         UNICORN_MODE=1
111*08b48e0bSAndroid Build Coastguard Worker         ;;
112*08b48e0bSAndroid Build Coastguard Worker    "T")
113*08b48e0bSAndroid Build Coastguard Worker         T_ARG="$OPTARG"
114*08b48e0bSAndroid Build Coastguard Worker         ;;
115*08b48e0bSAndroid Build Coastguard Worker    "?")
116*08b48e0bSAndroid Build Coastguard Worker         exit 1
117*08b48e0bSAndroid Build Coastguard Worker         ;;
118*08b48e0bSAndroid Build Coastguard Worker
119*08b48e0bSAndroid Build Coastguard Worker   esac
120*08b48e0bSAndroid Build Coastguard Worker
121*08b48e0bSAndroid Build Coastguard Workerdone
122*08b48e0bSAndroid Build Coastguard Worker
123*08b48e0bSAndroid Build Coastguard Workershift $((OPTIND-1))
124*08b48e0bSAndroid Build Coastguard Worker
125*08b48e0bSAndroid Build Coastguard WorkerTARGET_BIN="$1"
126*08b48e0bSAndroid Build Coastguard Worker
127*08b48e0bSAndroid Build Coastguard Workerif [ "$TARGET_BIN" = "" -o "$IN_DIR" = "" -o "$OUT_DIR" = "" ]; then
128*08b48e0bSAndroid Build Coastguard Worker
129*08b48e0bSAndroid Build Coastguard Worker  cat 1>&2 <<_EOF_
130*08b48e0bSAndroid Build Coastguard WorkerUsage: $0 [ options ] -- /path/to/target_app [ ... ]
131*08b48e0bSAndroid Build Coastguard Worker
132*08b48e0bSAndroid Build Coastguard WorkerRequired parameters:
133*08b48e0bSAndroid Build Coastguard Worker
134*08b48e0bSAndroid Build Coastguard Worker  -i dir        - input directory with the starting corpus
135*08b48e0bSAndroid Build Coastguard Worker  -o dir        - output directory for minimized files
136*08b48e0bSAndroid Build Coastguard Worker
137*08b48e0bSAndroid Build Coastguard WorkerExecution control settings:
138*08b48e0bSAndroid Build Coastguard Worker
139*08b48e0bSAndroid Build Coastguard Worker  -T tasks      - how many parallel processes to create (default=1, "all"=nproc)
140*08b48e0bSAndroid Build Coastguard Worker  -f file       - location read by the fuzzed program (default: stdin)
141*08b48e0bSAndroid Build Coastguard Worker  -m megs       - memory limit for child process (default=$MEM_LIMIT MB)
142*08b48e0bSAndroid Build Coastguard Worker  -t msec       - run time limit for child process (default: 5000ms)
143*08b48e0bSAndroid Build Coastguard Worker  -O            - use binary-only instrumentation (FRIDA mode)
144*08b48e0bSAndroid Build Coastguard Worker  -Q            - use binary-only instrumentation (QEMU mode)
145*08b48e0bSAndroid Build Coastguard Worker  -U            - use unicorn-based instrumentation (Unicorn mode)
146*08b48e0bSAndroid Build Coastguard Worker  -X            - use Nyx mode
147*08b48e0bSAndroid Build Coastguard Worker  
148*08b48e0bSAndroid Build Coastguard WorkerMinimization settings:
149*08b48e0bSAndroid Build Coastguard Worker
150*08b48e0bSAndroid Build Coastguard Worker  -A            - allow crashing and timeout inputs
151*08b48e0bSAndroid Build Coastguard Worker  -C            - keep crashing inputs, reject everything else
152*08b48e0bSAndroid Build Coastguard Worker  -e            - solve for edge coverage only, ignore hit counts
153*08b48e0bSAndroid Build Coastguard Worker
154*08b48e0bSAndroid Build Coastguard WorkerFor additional tips, please consult README.md.
155*08b48e0bSAndroid Build Coastguard Worker
156*08b48e0bSAndroid Build Coastguard WorkerEnvironment variables used:
157*08b48e0bSAndroid Build Coastguard WorkerAFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
158*08b48e0bSAndroid Build Coastguard WorkerAFL_NO_FORKSRV: run target via execve instead of using the forkserver
159*08b48e0bSAndroid Build Coastguard WorkerAFL_PATH: last resort location to find the afl-showmap binary
160*08b48e0bSAndroid Build Coastguard WorkerAFL_SKIP_BIN_CHECK: skip check for target binary
161*08b48e0bSAndroid Build Coastguard WorkerAFL_CUSTOM_MUTATOR_LIBRARY: custom mutator library (post_process and send)
162*08b48e0bSAndroid Build Coastguard WorkerAFL_PYTHON_MODULE: custom mutator library (post_process and send)
163*08b48e0bSAndroid Build Coastguard Worker_EOF_
164*08b48e0bSAndroid Build Coastguard Worker  exit 1
165*08b48e0bSAndroid Build Coastguard Workerfi
166*08b48e0bSAndroid Build Coastguard Worker
167*08b48e0bSAndroid Build Coastguard Worker# Do a sanity check to discourage the use of /tmp, since we can't really
168*08b48e0bSAndroid Build Coastguard Worker# handle this safely from a shell script.
169*08b48e0bSAndroid Build Coastguard Worker
170*08b48e0bSAndroid Build Coastguard Workerif [ "$AFL_ALLOW_TMP" = "" ]; then
171*08b48e0bSAndroid Build Coastguard Worker
172*08b48e0bSAndroid Build Coastguard Worker  echo "$IN_DIR" | grep -qE '^(/var)?/tmp/'
173*08b48e0bSAndroid Build Coastguard Worker  T1="$?"
174*08b48e0bSAndroid Build Coastguard Worker
175*08b48e0bSAndroid Build Coastguard Worker  echo "$TARGET_BIN" | grep -qE '^(/var)?/tmp/'
176*08b48e0bSAndroid Build Coastguard Worker  T2="$?"
177*08b48e0bSAndroid Build Coastguard Worker
178*08b48e0bSAndroid Build Coastguard Worker  echo "$OUT_DIR" | grep -qE '^(/var)?/tmp/'
179*08b48e0bSAndroid Build Coastguard Worker  T3="$?"
180*08b48e0bSAndroid Build Coastguard Worker
181*08b48e0bSAndroid Build Coastguard Worker  echo "$STDIN_FILE" | grep -qE '^(/var)?/tmp/'
182*08b48e0bSAndroid Build Coastguard Worker  T4="$?"
183*08b48e0bSAndroid Build Coastguard Worker
184*08b48e0bSAndroid Build Coastguard Worker  echo "$PWD" | grep -qE '^(/var)?/tmp/'
185*08b48e0bSAndroid Build Coastguard Worker  T5="$?"
186*08b48e0bSAndroid Build Coastguard Worker
187*08b48e0bSAndroid Build Coastguard Worker  if [ "$T1" = "0" -o "$T2" = "0" -o "$T3" = "0" -o "$T4" = "0" -o "$T5" = "0" ]; then
188*08b48e0bSAndroid Build Coastguard Worker    echo "[-] Warning: do not use this script in /tmp or /var/tmp for security reasons." 1>&2
189*08b48e0bSAndroid Build Coastguard Worker  fi
190*08b48e0bSAndroid Build Coastguard Worker
191*08b48e0bSAndroid Build Coastguard Workerfi
192*08b48e0bSAndroid Build Coastguard Worker
193*08b48e0bSAndroid Build Coastguard Worker# If @@ is specified, but there's no -f, let's come up with a temporary input
194*08b48e0bSAndroid Build Coastguard Worker# file name.
195*08b48e0bSAndroid Build Coastguard Worker
196*08b48e0bSAndroid Build Coastguard WorkerTRACE_DIR="$OUT_DIR/.traces"
197*08b48e0bSAndroid Build Coastguard Worker
198*08b48e0bSAndroid Build Coastguard Workerif [ "$STDIN_FILE" = "" ]; then
199*08b48e0bSAndroid Build Coastguard Worker
200*08b48e0bSAndroid Build Coastguard Worker  if echo "$*" | grep -qF '@@'; then
201*08b48e0bSAndroid Build Coastguard Worker    STDIN_FILE="$TRACE_DIR/.cur_input"
202*08b48e0bSAndroid Build Coastguard Worker  fi
203*08b48e0bSAndroid Build Coastguard Worker
204*08b48e0bSAndroid Build Coastguard Workerfi
205*08b48e0bSAndroid Build Coastguard Worker
206*08b48e0bSAndroid Build Coastguard Worker# Check for obvious errors.
207*08b48e0bSAndroid Build Coastguard Worker
208*08b48e0bSAndroid Build Coastguard Workerif [ ! "$T_ARG" = "" -a -n "$F_ARG" -a ! "$NYX_MODE" == 1 ]; then
209*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: -T and -f can not be used together." 1>&2
210*08b48e0bSAndroid Build Coastguard Worker  exit 1
211*08b48e0bSAndroid Build Coastguard Workerfi
212*08b48e0bSAndroid Build Coastguard Worker
213*08b48e0bSAndroid Build Coastguard Workerif [ ! "$MEM_LIMIT" = "none" ]; then
214*08b48e0bSAndroid Build Coastguard Worker
215*08b48e0bSAndroid Build Coastguard Worker  if [ "$MEM_LIMIT" -lt "5" ]; then
216*08b48e0bSAndroid Build Coastguard Worker    echo "[-] Error: dangerously low memory limit." 1>&2
217*08b48e0bSAndroid Build Coastguard Worker    exit 1
218*08b48e0bSAndroid Build Coastguard Worker  fi
219*08b48e0bSAndroid Build Coastguard Worker
220*08b48e0bSAndroid Build Coastguard Workerfi
221*08b48e0bSAndroid Build Coastguard Worker
222*08b48e0bSAndroid Build Coastguard Workerif [ ! "$TIMEOUT" = "none" ]; then
223*08b48e0bSAndroid Build Coastguard Worker
224*08b48e0bSAndroid Build Coastguard Worker  if [ "$TIMEOUT" -lt "10" ]; then
225*08b48e0bSAndroid Build Coastguard Worker    echo "[-] Error: dangerously low timeout." 1>&2
226*08b48e0bSAndroid Build Coastguard Worker    exit 1
227*08b48e0bSAndroid Build Coastguard Worker  fi
228*08b48e0bSAndroid Build Coastguard Worker
229*08b48e0bSAndroid Build Coastguard Workerfi
230*08b48e0bSAndroid Build Coastguard Worker
231*08b48e0bSAndroid Build Coastguard Workerif [ "$NYX_MODE" = "" ]; then
232*08b48e0bSAndroid Build Coastguard Worker  if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
233*08b48e0bSAndroid Build Coastguard Worker
234*08b48e0bSAndroid Build Coastguard Worker    TNEW="`which "$TARGET_BIN" 2>/dev/null`"
235*08b48e0bSAndroid Build Coastguard Worker
236*08b48e0bSAndroid Build Coastguard Worker    if [ ! -f "$TNEW" -o ! -x "$TNEW" ]; then
237*08b48e0bSAndroid Build Coastguard Worker      echo "[-] Error: binary '$TARGET_BIN' not found or not executable." 1>&2
238*08b48e0bSAndroid Build Coastguard Worker      exit 1
239*08b48e0bSAndroid Build Coastguard Worker    fi
240*08b48e0bSAndroid Build Coastguard Worker
241*08b48e0bSAndroid Build Coastguard Worker    TARGET_BIN="$TNEW"
242*08b48e0bSAndroid Build Coastguard Worker
243*08b48e0bSAndroid Build Coastguard Worker  fi
244*08b48e0bSAndroid Build Coastguard Worker
245*08b48e0bSAndroid Build Coastguard Workerfi
246*08b48e0bSAndroid Build Coastguard Worker
247*08b48e0bSAndroid Build Coastguard Workergrep -aq AFL_DUMP_MAP_SIZE "$TARGET_BIN" && {
248*08b48e0bSAndroid Build Coastguard Worker  echo "[!] Trying to obtain the map size of the target ..."
249*08b48e0bSAndroid Build Coastguard Worker  MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null`
250*08b48e0bSAndroid Build Coastguard Worker  test -n "$MAPSIZE" && {
251*08b48e0bSAndroid Build Coastguard Worker    export AFL_MAP_SIZE=$MAPSIZE
252*08b48e0bSAndroid Build Coastguard Worker    echo "[+] Setting AFL_MAP_SIZE=$MAPSIZE"
253*08b48e0bSAndroid Build Coastguard Worker  }
254*08b48e0bSAndroid Build Coastguard Worker}
255*08b48e0bSAndroid Build Coastguard Worker
256*08b48e0bSAndroid Build Coastguard Workerif [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" -a "$NYX_MODE" = "" ]; then
257*08b48e0bSAndroid Build Coastguard Worker
258*08b48e0bSAndroid Build Coastguard Worker  if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then
259*08b48e0bSAndroid Build Coastguard Worker    echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2
260*08b48e0bSAndroid Build Coastguard Worker    exit 1
261*08b48e0bSAndroid Build Coastguard Worker  fi
262*08b48e0bSAndroid Build Coastguard Worker
263*08b48e0bSAndroid Build Coastguard Workerfi
264*08b48e0bSAndroid Build Coastguard Worker
265*08b48e0bSAndroid Build Coastguard Workerif [ ! -d "$IN_DIR" ]; then
266*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: directory '$IN_DIR' not found." 1>&2
267*08b48e0bSAndroid Build Coastguard Worker  exit 1
268*08b48e0bSAndroid Build Coastguard Workerfi
269*08b48e0bSAndroid Build Coastguard Worker
270*08b48e0bSAndroid Build Coastguard Workertest -d "$IN_DIR/default" && IN_DIR="$IN_DIR/default"
271*08b48e0bSAndroid Build Coastguard Workertest -d "$IN_DIR/queue" && IN_DIR="$IN_DIR/queue"
272*08b48e0bSAndroid Build Coastguard Worker
273*08b48e0bSAndroid Build Coastguard Workerfind "$OUT_DIR" -name 'id[:_]*' -maxdepth 1 -exec rm -- {} \; 2>/dev/null
274*08b48e0bSAndroid Build Coastguard Workerrm -rf "$TRACE_DIR" 2>/dev/null
275*08b48e0bSAndroid Build Coastguard Worker
276*08b48e0bSAndroid Build Coastguard Workerrmdir "$OUT_DIR" 2>/dev/null
277*08b48e0bSAndroid Build Coastguard Worker
278*08b48e0bSAndroid Build Coastguard Workerif [ -d "$OUT_DIR" ]; then
279*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: directory '$OUT_DIR' exists and is not empty - delete it first." 1>&2
280*08b48e0bSAndroid Build Coastguard Worker  exit 1
281*08b48e0bSAndroid Build Coastguard Workerfi
282*08b48e0bSAndroid Build Coastguard Worker
283*08b48e0bSAndroid Build Coastguard Workermkdir -m 700 -p "$TRACE_DIR" || exit 1
284*08b48e0bSAndroid Build Coastguard Worker
285*08b48e0bSAndroid Build Coastguard Workerif [ ! "$STDIN_FILE" = "" ]; then
286*08b48e0bSAndroid Build Coastguard Worker  rm -f "$STDIN_FILE" || exit 1
287*08b48e0bSAndroid Build Coastguard Worker  touch "$STDIN_FILE" || exit 1
288*08b48e0bSAndroid Build Coastguard Workerfi
289*08b48e0bSAndroid Build Coastguard Worker
290*08b48e0bSAndroid Build Coastguard WorkerSHOWMAP=`command -v afl-showmap 2>/dev/null`
291*08b48e0bSAndroid Build Coastguard Worker
292*08b48e0bSAndroid Build Coastguard Workerif [ -z "$SHOWMAP" ]; then
293*08b48e0bSAndroid Build Coastguard Worker  TMP="${0%/afl-cmin.bash}/afl-showmap"
294*08b48e0bSAndroid Build Coastguard Worker  if [ -x "$TMP" ]; then
295*08b48e0bSAndroid Build Coastguard Worker    SHOWMAP=$TMP
296*08b48e0bSAndroid Build Coastguard Worker  fi
297*08b48e0bSAndroid Build Coastguard Workerfi
298*08b48e0bSAndroid Build Coastguard Worker
299*08b48e0bSAndroid Build Coastguard Workerif [ -z "$SHOWMAP" -a -x "./afl-showmap" ]; then
300*08b48e0bSAndroid Build Coastguard Worker  SHOWMAP="./afl-showmap"
301*08b48e0bSAndroid Build Coastguard Workerelse
302*08b48e0bSAndroid Build Coastguard Worker  if [ -n "$AFL_PATH" ]; then
303*08b48e0bSAndroid Build Coastguard Worker    SHOWMAP="$AFL_PATH/afl-showmap"
304*08b48e0bSAndroid Build Coastguard Worker  fi
305*08b48e0bSAndroid Build Coastguard Workerfi
306*08b48e0bSAndroid Build Coastguard Worker
307*08b48e0bSAndroid Build Coastguard Workerif [ ! -x "$SHOWMAP" ]; then
308*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: can't find 'afl-showmap' - please set AFL_PATH." 1>&2
309*08b48e0bSAndroid Build Coastguard Worker  rm -rf "$TRACE_DIR"
310*08b48e0bSAndroid Build Coastguard Worker  exit 1
311*08b48e0bSAndroid Build Coastguard Workerfi
312*08b48e0bSAndroid Build Coastguard Worker
313*08b48e0bSAndroid Build Coastguard WorkerTHREADS=
314*08b48e0bSAndroid Build Coastguard Workerif [ ! "$T_ARG" = "" ]; then
315*08b48e0bSAndroid Build Coastguard Worker  if [ "$T_ARG" = "all" ]; then
316*08b48e0bSAndroid Build Coastguard Worker    THREADS=$(nproc)
317*08b48e0bSAndroid Build Coastguard Worker  else
318*08b48e0bSAndroid Build Coastguard Worker    if [ "$T_ARG" -gt 1 -a "$T_ARG" -le "$(nproc)" ]; then
319*08b48e0bSAndroid Build Coastguard Worker      THREADS=$T_ARG
320*08b48e0bSAndroid Build Coastguard Worker    else
321*08b48e0bSAndroid Build Coastguard Worker      echo "[-] Error: -T parameter must between 2 and $(nproc) or \"all\"." 1>&2
322*08b48e0bSAndroid Build Coastguard Worker    fi
323*08b48e0bSAndroid Build Coastguard Worker  fi
324*08b48e0bSAndroid Build Coastguard Workerelse
325*08b48e0bSAndroid Build Coastguard Worker  if [ -z "$F_ARG" ]; then
326*08b48e0bSAndroid Build Coastguard Worker    echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?"
327*08b48e0bSAndroid Build Coastguard Worker  fi
328*08b48e0bSAndroid Build Coastguard Workerfi
329*08b48e0bSAndroid Build Coastguard Worker
330*08b48e0bSAndroid Build Coastguard WorkerIN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`))
331*08b48e0bSAndroid Build Coastguard Worker
332*08b48e0bSAndroid Build Coastguard Workerif [ "$IN_COUNT" = "0" ]; then
333*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Hmm, no inputs in the target directory. Nothing to be done."
334*08b48e0bSAndroid Build Coastguard Worker  rm -rf "$TRACE_DIR"
335*08b48e0bSAndroid Build Coastguard Worker  exit 1
336*08b48e0bSAndroid Build Coastguard Workerfi
337*08b48e0bSAndroid Build Coastguard Worker
338*08b48e0bSAndroid Build Coastguard Workerecho "[*] Are you aware that afl-cmin is faster than this afl-cmin.bash script?"
339*08b48e0bSAndroid Build Coastguard Workerecho "[+] Found $IN_COUNT files for minimizing."
340*08b48e0bSAndroid Build Coastguard Worker
341*08b48e0bSAndroid Build Coastguard Workerif [ -n "$THREADS" ]; then
342*08b48e0bSAndroid Build Coastguard Worker  if [ "$IN_COUNT" -lt "$THREADS" ]; then
343*08b48e0bSAndroid Build Coastguard Worker    THREADS=$IN_COUNT
344*08b48e0bSAndroid Build Coastguard Worker    echo "[!] WARNING: less inputs than threads, reducing threads to $THREADS and likely the overhead of threading makes things slower..."
345*08b48e0bSAndroid Build Coastguard Worker  fi
346*08b48e0bSAndroid Build Coastguard Workerfi
347*08b48e0bSAndroid Build Coastguard Worker
348*08b48e0bSAndroid Build Coastguard WorkerFIRST_FILE=`ls "$IN_DIR" | head -1`
349*08b48e0bSAndroid Build Coastguard Worker
350*08b48e0bSAndroid Build Coastguard Worker# Make sure that we're not dealing with a directory.
351*08b48e0bSAndroid Build Coastguard Worker
352*08b48e0bSAndroid Build Coastguard Workerif [ -d "$IN_DIR/$FIRST_FILE" ]; then
353*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: The target directory contains subdirectories - please fix." 1>&2
354*08b48e0bSAndroid Build Coastguard Worker  rm -rf "$TRACE_DIR"
355*08b48e0bSAndroid Build Coastguard Worker  exit 1
356*08b48e0bSAndroid Build Coastguard Workerfi
357*08b48e0bSAndroid Build Coastguard Worker
358*08b48e0bSAndroid Build Coastguard Worker# Check for the more efficient way to copy files...
359*08b48e0bSAndroid Build Coastguard Worker
360*08b48e0bSAndroid Build Coastguard Workerif ln "$IN_DIR/$FIRST_FILE" "$TRACE_DIR/.link_test" 2>/dev/null; then
361*08b48e0bSAndroid Build Coastguard Worker  CP_TOOL=ln
362*08b48e0bSAndroid Build Coastguard Workerelse
363*08b48e0bSAndroid Build Coastguard Worker  CP_TOOL=cp
364*08b48e0bSAndroid Build Coastguard Workerfi
365*08b48e0bSAndroid Build Coastguard Worker
366*08b48e0bSAndroid Build Coastguard Worker# Make sure that we can actually get anything out of afl-showmap before we
367*08b48e0bSAndroid Build Coastguard Worker# waste too much time.
368*08b48e0bSAndroid Build Coastguard Worker
369*08b48e0bSAndroid Build Coastguard Workerecho "[*] Testing the target binary..."
370*08b48e0bSAndroid Build Coastguard Worker
371*08b48e0bSAndroid Build Coastguard Workerif [ "$STDIN_FILE" = "" ]; then
372*08b48e0bSAndroid Build Coastguard Worker
373*08b48e0bSAndroid Build Coastguard Worker  AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$FIRST_FILE"
374*08b48e0bSAndroid Build Coastguard Worker
375*08b48e0bSAndroid Build Coastguard Workerelse
376*08b48e0bSAndroid Build Coastguard Worker
377*08b48e0bSAndroid Build Coastguard Worker  cp "$IN_DIR/$FIRST_FILE" "$STDIN_FILE"
378*08b48e0bSAndroid Build Coastguard Worker  AFL_CMIN_ALLOW_ANY=1 "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/.run_test" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
379*08b48e0bSAndroid Build Coastguard Worker
380*08b48e0bSAndroid Build Coastguard Workerfi
381*08b48e0bSAndroid Build Coastguard Worker
382*08b48e0bSAndroid Build Coastguard WorkerFIRST_COUNT=$((`grep -c . "$TRACE_DIR/.run_test"`))
383*08b48e0bSAndroid Build Coastguard Worker
384*08b48e0bSAndroid Build Coastguard Workerif [ "$FIRST_COUNT" -gt "0" ]; then
385*08b48e0bSAndroid Build Coastguard Worker
386*08b48e0bSAndroid Build Coastguard Worker  echo "[+] OK, $FIRST_COUNT tuples recorded."
387*08b48e0bSAndroid Build Coastguard Worker
388*08b48e0bSAndroid Build Coastguard Workerelse
389*08b48e0bSAndroid Build Coastguard Worker
390*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: no instrumentation output detected (perhaps crash or timeout)." 1>&2
391*08b48e0bSAndroid Build Coastguard Worker  test "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR"
392*08b48e0bSAndroid Build Coastguard Worker  exit 1
393*08b48e0bSAndroid Build Coastguard Worker
394*08b48e0bSAndroid Build Coastguard Workerfi
395*08b48e0bSAndroid Build Coastguard Worker
396*08b48e0bSAndroid Build Coastguard WorkerTMPFILE=$OUT_DIR/.list.$$
397*08b48e0bSAndroid Build Coastguard Workerif [ ! "$THREADS" = "" ]; then
398*08b48e0bSAndroid Build Coastguard Worker  ls -- "$IN_DIR" > $TMPFILE 2>/dev/null
399*08b48e0bSAndroid Build Coastguard Worker  IN_COUNT=$(cat $TMPFILE | wc -l)
400*08b48e0bSAndroid Build Coastguard Worker  SPLIT=$(($IN_COUNT / $THREADS))
401*08b48e0bSAndroid Build Coastguard Worker  if [ "$(($IN_COUNT % $THREADS))" -gt 0 ]; then
402*08b48e0bSAndroid Build Coastguard Worker    SPLIT=$(($SPLIT + 1))
403*08b48e0bSAndroid Build Coastguard Worker  fi
404*08b48e0bSAndroid Build Coastguard Worker  echo "[+] Splitting workload into $THREADS tasks with $SPLIT items on average each."
405*08b48e0bSAndroid Build Coastguard Worker  split -l $SPLIT $TMPFILE $TMPFILE.
406*08b48e0bSAndroid Build Coastguard Workerfi
407*08b48e0bSAndroid Build Coastguard Worker
408*08b48e0bSAndroid Build Coastguard Worker# Let's roll!
409*08b48e0bSAndroid Build Coastguard Worker
410*08b48e0bSAndroid Build Coastguard Worker#############################
411*08b48e0bSAndroid Build Coastguard Worker# STEP 1: COLLECTING TRACES #
412*08b48e0bSAndroid Build Coastguard Worker#############################
413*08b48e0bSAndroid Build Coastguard Worker
414*08b48e0bSAndroid Build Coastguard Workerecho "[*] Obtaining traces for input files in '$IN_DIR'..."
415*08b48e0bSAndroid Build Coastguard Worker
416*08b48e0bSAndroid Build Coastguard Workerif [ "$THREADS" = "" ]; then
417*08b48e0bSAndroid Build Coastguard Worker(
418*08b48e0bSAndroid Build Coastguard Worker
419*08b48e0bSAndroid Build Coastguard Worker  CUR=0
420*08b48e0bSAndroid Build Coastguard Worker
421*08b48e0bSAndroid Build Coastguard Worker  if [ "$STDIN_FILE" = "" ]; then
422*08b48e0bSAndroid Build Coastguard Worker
423*08b48e0bSAndroid Build Coastguard Worker    ls "$IN_DIR" | while read -r fn; do
424*08b48e0bSAndroid Build Coastguard Worker
425*08b48e0bSAndroid Build Coastguard Worker      if [ -s "$IN_DIR/$fn" ]; then
426*08b48e0bSAndroid Build Coastguard Worker
427*08b48e0bSAndroid Build Coastguard Worker        CUR=$((CUR+1))
428*08b48e0bSAndroid Build Coastguard Worker        printf "\\r    Processing file $CUR/$IN_COUNT... "
429*08b48e0bSAndroid Build Coastguard Worker
430*08b48e0bSAndroid Build Coastguard Worker        "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn"
431*08b48e0bSAndroid Build Coastguard Worker
432*08b48e0bSAndroid Build Coastguard Worker      fi
433*08b48e0bSAndroid Build Coastguard Worker
434*08b48e0bSAndroid Build Coastguard Worker    done
435*08b48e0bSAndroid Build Coastguard Worker
436*08b48e0bSAndroid Build Coastguard Worker  else
437*08b48e0bSAndroid Build Coastguard Worker
438*08b48e0bSAndroid Build Coastguard Worker    ls "$IN_DIR" | while read -r fn; do
439*08b48e0bSAndroid Build Coastguard Worker
440*08b48e0bSAndroid Build Coastguard Worker      if [ -s "$IN_DIR/$fn" ]; then
441*08b48e0bSAndroid Build Coastguard Worker
442*08b48e0bSAndroid Build Coastguard Worker        CUR=$((CUR+1))
443*08b48e0bSAndroid Build Coastguard Worker        printf "\\r    Processing file $CUR/$IN_COUNT... "
444*08b48e0bSAndroid Build Coastguard Worker
445*08b48e0bSAndroid Build Coastguard Worker        cp "$IN_DIR/$fn" "$STDIN_FILE"
446*08b48e0bSAndroid Build Coastguard Worker        "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
447*08b48e0bSAndroid Build Coastguard Worker
448*08b48e0bSAndroid Build Coastguard Worker      fi
449*08b48e0bSAndroid Build Coastguard Worker
450*08b48e0bSAndroid Build Coastguard Worker    done
451*08b48e0bSAndroid Build Coastguard Worker
452*08b48e0bSAndroid Build Coastguard Worker  fi
453*08b48e0bSAndroid Build Coastguard Worker
454*08b48e0bSAndroid Build Coastguard Worker  echo
455*08b48e0bSAndroid Build Coastguard Worker
456*08b48e0bSAndroid Build Coastguard Worker)
457*08b48e0bSAndroid Build Coastguard Worker
458*08b48e0bSAndroid Build Coastguard Workerelse
459*08b48e0bSAndroid Build Coastguard Worker
460*08b48e0bSAndroid Build Coastguard Worker  PIDS=
461*08b48e0bSAndroid Build Coastguard Worker  CNT=0
462*08b48e0bSAndroid Build Coastguard Worker  for inputs in $(ls ${TMPFILE}.*); do
463*08b48e0bSAndroid Build Coastguard Worker
464*08b48e0bSAndroid Build Coastguard Worker(
465*08b48e0bSAndroid Build Coastguard Worker
466*08b48e0bSAndroid Build Coastguard Worker  if [ "$STDIN_FILE" = "" ]; then
467*08b48e0bSAndroid Build Coastguard Worker
468*08b48e0bSAndroid Build Coastguard Worker    cat $inputs | while read -r fn; do
469*08b48e0bSAndroid Build Coastguard Worker
470*08b48e0bSAndroid Build Coastguard Worker      if [ -s "$IN_DIR/$fn" ]; then
471*08b48e0bSAndroid Build Coastguard Worker
472*08b48e0bSAndroid Build Coastguard Worker        "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn"
473*08b48e0bSAndroid Build Coastguard Worker
474*08b48e0bSAndroid Build Coastguard Worker      fi
475*08b48e0bSAndroid Build Coastguard Worker
476*08b48e0bSAndroid Build Coastguard Worker    done
477*08b48e0bSAndroid Build Coastguard Worker
478*08b48e0bSAndroid Build Coastguard Worker  else
479*08b48e0bSAndroid Build Coastguard Worker
480*08b48e0bSAndroid Build Coastguard Worker    if [ -s "$IN_DIR/$fn" ]; then
481*08b48e0bSAndroid Build Coastguard Worker      STDIN_FILE="$inputs.$$"
482*08b48e0bSAndroid Build Coastguard Worker      cat $inputs | while read -r fn; do
483*08b48e0bSAndroid Build Coastguard Worker
484*08b48e0bSAndroid Build Coastguard Worker        cp "$IN_DIR/$fn" "$STDIN_FILE"
485*08b48e0bSAndroid Build Coastguard Worker        "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
486*08b48e0bSAndroid Build Coastguard Worker
487*08b48e0bSAndroid Build Coastguard Worker      done
488*08b48e0bSAndroid Build Coastguard Worker
489*08b48e0bSAndroid Build Coastguard Worker    fi
490*08b48e0bSAndroid Build Coastguard Worker
491*08b48e0bSAndroid Build Coastguard Worker  fi
492*08b48e0bSAndroid Build Coastguard Worker
493*08b48e0bSAndroid Build Coastguard Worker) &
494*08b48e0bSAndroid Build Coastguard Worker
495*08b48e0bSAndroid Build Coastguard Worker  PIDS="$PIDS $!"
496*08b48e0bSAndroid Build Coastguard Worker  done
497*08b48e0bSAndroid Build Coastguard Worker
498*08b48e0bSAndroid Build Coastguard Worker  echo "[+] Waiting for running tasks IDs:$PIDS"
499*08b48e0bSAndroid Build Coastguard Worker  wait
500*08b48e0bSAndroid Build Coastguard Worker  echo "[+] all $THREADS running tasks completed."
501*08b48e0bSAndroid Build Coastguard Worker  rm -f ${TMPFILE}*
502*08b48e0bSAndroid Build Coastguard Worker
503*08b48e0bSAndroid Build Coastguard Worker  #echo trace dir files: $(ls $TRACE_DIR/*|wc -l)
504*08b48e0bSAndroid Build Coastguard Worker
505*08b48e0bSAndroid Build Coastguard Workerfi
506*08b48e0bSAndroid Build Coastguard Worker
507*08b48e0bSAndroid Build Coastguard Worker
508*08b48e0bSAndroid Build Coastguard Worker##########################
509*08b48e0bSAndroid Build Coastguard Worker# STEP 2: SORTING TUPLES #
510*08b48e0bSAndroid Build Coastguard Worker##########################
511*08b48e0bSAndroid Build Coastguard Worker
512*08b48e0bSAndroid Build Coastguard Worker# With this out of the way, we sort all tuples by popularity across all
513*08b48e0bSAndroid Build Coastguard Worker# datasets. The reasoning here is that we won't be able to avoid the files
514*08b48e0bSAndroid Build Coastguard Worker# that trigger unique tuples anyway, so we will want to start with them and
515*08b48e0bSAndroid Build Coastguard Worker# see what's left.
516*08b48e0bSAndroid Build Coastguard Worker
517*08b48e0bSAndroid Build Coastguard Workerecho "[*] Sorting trace sets (this may take a while)..."
518*08b48e0bSAndroid Build Coastguard Worker
519*08b48e0bSAndroid Build Coastguard Workerls "$IN_DIR" | sed "s#^#$TRACE_DIR/#" | tr '\n' '\0' | xargs -0 -n 1 cat | \
520*08b48e0bSAndroid Build Coastguard Worker  sort | uniq -c | sort -k 1,1 -n >"$TRACE_DIR/.all_uniq"
521*08b48e0bSAndroid Build Coastguard Worker
522*08b48e0bSAndroid Build Coastguard WorkerTUPLE_COUNT=$((`grep -c . "$TRACE_DIR/.all_uniq"`))
523*08b48e0bSAndroid Build Coastguard Worker
524*08b48e0bSAndroid Build Coastguard Workerecho "[+] Found $TUPLE_COUNT unique tuples across $IN_COUNT files."
525*08b48e0bSAndroid Build Coastguard Worker
526*08b48e0bSAndroid Build Coastguard Worker#####################################
527*08b48e0bSAndroid Build Coastguard Worker# STEP 3: SELECTING CANDIDATE FILES #
528*08b48e0bSAndroid Build Coastguard Worker#####################################
529*08b48e0bSAndroid Build Coastguard Worker
530*08b48e0bSAndroid Build Coastguard Worker# The next step is to find the best candidate for each tuple. The "best"
531*08b48e0bSAndroid Build Coastguard Worker# part is understood simply as the smallest input that includes a particular
532*08b48e0bSAndroid Build Coastguard Worker# tuple in its trace. Empirical evidence suggests that this produces smaller
533*08b48e0bSAndroid Build Coastguard Worker# datasets than more involved algorithms that could be still pulled off in
534*08b48e0bSAndroid Build Coastguard Worker# a shell script.
535*08b48e0bSAndroid Build Coastguard Worker
536*08b48e0bSAndroid Build Coastguard Workerecho "[*] Finding best candidates for each tuple..."
537*08b48e0bSAndroid Build Coastguard Worker
538*08b48e0bSAndroid Build Coastguard WorkerCUR=0
539*08b48e0bSAndroid Build Coastguard Worker
540*08b48e0bSAndroid Build Coastguard Workerls -rS "$IN_DIR" | while read -r fn; do
541*08b48e0bSAndroid Build Coastguard Worker
542*08b48e0bSAndroid Build Coastguard Worker  CUR=$((CUR+1))
543*08b48e0bSAndroid Build Coastguard Worker  printf "\\r    Processing file $CUR/$IN_COUNT... "
544*08b48e0bSAndroid Build Coastguard Worker
545*08b48e0bSAndroid Build Coastguard Worker  sed "s#\$# $fn#" "$TRACE_DIR/$fn" >>"$TRACE_DIR/.candidate_list"
546*08b48e0bSAndroid Build Coastguard Worker
547*08b48e0bSAndroid Build Coastguard Worker  test -s "$TRACE_DIR/$fn" || echo Warning: $fn is ignored because of crashing the target
548*08b48e0bSAndroid Build Coastguard Worker
549*08b48e0bSAndroid Build Coastguard Workerdone
550*08b48e0bSAndroid Build Coastguard Worker
551*08b48e0bSAndroid Build Coastguard Workerecho
552*08b48e0bSAndroid Build Coastguard Worker
553*08b48e0bSAndroid Build Coastguard Worker##############################
554*08b48e0bSAndroid Build Coastguard Worker# STEP 4: LOADING CANDIDATES #
555*08b48e0bSAndroid Build Coastguard Worker##############################
556*08b48e0bSAndroid Build Coastguard Worker
557*08b48e0bSAndroid Build Coastguard Worker# At this point, we have a file of tuple-file pairs, sorted by file size
558*08b48e0bSAndroid Build Coastguard Worker# in ascending order (as a consequence of ls -rS). By doing sort keyed
559*08b48e0bSAndroid Build Coastguard Worker# only by tuple (-k 1,1) and configured to output only the first line for
560*08b48e0bSAndroid Build Coastguard Worker# every key (-s -u), we end up with the smallest file for each tuple.
561*08b48e0bSAndroid Build Coastguard Worker
562*08b48e0bSAndroid Build Coastguard Workerecho "[*] Sorting candidate list (be patient)..."
563*08b48e0bSAndroid Build Coastguard Worker
564*08b48e0bSAndroid Build Coastguard Workersort -k1,1 -s -u "$TRACE_DIR/.candidate_list" | \
565*08b48e0bSAndroid Build Coastguard Worker  sed 's/^/BEST_FILE[/;s/ /]="/;s/$/"/' >"$TRACE_DIR/.candidate_script"
566*08b48e0bSAndroid Build Coastguard Worker
567*08b48e0bSAndroid Build Coastguard Workerif [ ! -s "$TRACE_DIR/.candidate_script" ]; then
568*08b48e0bSAndroid Build Coastguard Worker  echo "[-] Error: no traces obtained from test cases, check syntax!" 1>&2
569*08b48e0bSAndroid Build Coastguard Worker  test "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR"
570*08b48e0bSAndroid Build Coastguard Worker  exit 1
571*08b48e0bSAndroid Build Coastguard Workerfi
572*08b48e0bSAndroid Build Coastguard Worker
573*08b48e0bSAndroid Build Coastguard Worker# The sed command converted the sorted list to a shell script that populates
574*08b48e0bSAndroid Build Coastguard Worker# BEST_FILE[tuple]="fname". Let's load that!
575*08b48e0bSAndroid Build Coastguard Worker
576*08b48e0bSAndroid Build Coastguard Worker. "$TRACE_DIR/.candidate_script"
577*08b48e0bSAndroid Build Coastguard Worker
578*08b48e0bSAndroid Build Coastguard Worker##########################
579*08b48e0bSAndroid Build Coastguard Worker# STEP 5: WRITING OUTPUT #
580*08b48e0bSAndroid Build Coastguard Worker##########################
581*08b48e0bSAndroid Build Coastguard Worker
582*08b48e0bSAndroid Build Coastguard Worker# The final trick is to grab the top pick for each tuple, unless said tuple is
583*08b48e0bSAndroid Build Coastguard Worker# already set due to the inclusion of an earlier candidate; and then put all
584*08b48e0bSAndroid Build Coastguard Worker# tuples associated with the newly-added file to the "already have" list. The
585*08b48e0bSAndroid Build Coastguard Worker# loop works from least popular tuples and toward the most common ones.
586*08b48e0bSAndroid Build Coastguard Worker
587*08b48e0bSAndroid Build Coastguard Workerecho "[*] Processing candidates and writing output files..."
588*08b48e0bSAndroid Build Coastguard Worker
589*08b48e0bSAndroid Build Coastguard WorkerCUR=0
590*08b48e0bSAndroid Build Coastguard Worker
591*08b48e0bSAndroid Build Coastguard Workertouch "$TRACE_DIR/.already_have"
592*08b48e0bSAndroid Build Coastguard Worker
593*08b48e0bSAndroid Build Coastguard Workerwhile read -r cnt tuple; do
594*08b48e0bSAndroid Build Coastguard Worker
595*08b48e0bSAndroid Build Coastguard Worker  CUR=$((CUR+1))
596*08b48e0bSAndroid Build Coastguard Worker  printf "\\r    Processing tuple $CUR/$TUPLE_COUNT with count $cnt... "
597*08b48e0bSAndroid Build Coastguard Worker
598*08b48e0bSAndroid Build Coastguard Worker  # If we already have this tuple, skip it.
599*08b48e0bSAndroid Build Coastguard Worker
600*08b48e0bSAndroid Build Coastguard Worker  grep -q "^$tuple\$" "$TRACE_DIR/.already_have" && continue
601*08b48e0bSAndroid Build Coastguard Worker
602*08b48e0bSAndroid Build Coastguard Worker  FN=${BEST_FILE[tuple]}
603*08b48e0bSAndroid Build Coastguard Worker
604*08b48e0bSAndroid Build Coastguard Worker#  echo "tuple nr $CUR ($tuple cnt=$cnt) -> $FN" >> "$TRACE_DIR/.log"
605*08b48e0bSAndroid Build Coastguard Worker  $CP_TOOL "$IN_DIR/$FN" "$OUT_DIR/$FN"
606*08b48e0bSAndroid Build Coastguard Worker
607*08b48e0bSAndroid Build Coastguard Worker  if [ "$((CUR % 5))" = "0" ]; then
608*08b48e0bSAndroid Build Coastguard Worker    sort -u "$TRACE_DIR/$FN" "$TRACE_DIR/.already_have" >"$TRACE_DIR/.tmp"
609*08b48e0bSAndroid Build Coastguard Worker    mv -f "$TRACE_DIR/.tmp" "$TRACE_DIR/.already_have"
610*08b48e0bSAndroid Build Coastguard Worker  else
611*08b48e0bSAndroid Build Coastguard Worker    cat "$TRACE_DIR/$FN" >>"$TRACE_DIR/.already_have"
612*08b48e0bSAndroid Build Coastguard Worker  fi
613*08b48e0bSAndroid Build Coastguard Worker
614*08b48e0bSAndroid Build Coastguard Workerdone <"$TRACE_DIR/.all_uniq"
615*08b48e0bSAndroid Build Coastguard Worker
616*08b48e0bSAndroid Build Coastguard Workerecho
617*08b48e0bSAndroid Build Coastguard Worker
618*08b48e0bSAndroid Build Coastguard WorkerOUT_COUNT=`ls -- "$OUT_DIR" | wc -l`
619*08b48e0bSAndroid Build Coastguard Worker
620*08b48e0bSAndroid Build Coastguard Workerif [ "$OUT_COUNT" = "1" ]; then
621*08b48e0bSAndroid Build Coastguard Worker  echo "[!] WARNING: All test cases had the same traces, check syntax!"
622*08b48e0bSAndroid Build Coastguard Workerfi
623*08b48e0bSAndroid Build Coastguard Worker
624*08b48e0bSAndroid Build Coastguard Workerecho "[+] Narrowed down to $OUT_COUNT files, saved in '$OUT_DIR'."
625*08b48e0bSAndroid Build Coastguard Workerecho
626*08b48e0bSAndroid Build Coastguard Worker
627*08b48e0bSAndroid Build Coastguard Workertest "$AFL_KEEP_TRACES" = "" && rm -rf "$TRACE_DIR"
628*08b48e0bSAndroid Build Coastguard Worker
629*08b48e0bSAndroid Build Coastguard Workerexit 0
630