blob: 8af45f62544a7381b8f4a38768dfd7c6a427064e [file] [log] [blame]
drh4d35c412015-04-28 00:53:26 +00001#!/usr/bin/tclsh
2#
3# Run this script in order to rebuild the fuzzdata1.txt file containing
4# fuzzer data for the fuzzershell utility that is create by afl-fuzz.
5#
6# This script gathers all of the test cases identified by afl-fuzz and
7# runs afl-cmin and afl-tmin over them all to try to generate a mimimum
8# set of tests that cover all observed behavior.
9#
10# Options:
11#
12# --afl-bin DIR1 DIR1 contains the AFL binaries
13# --fuzzershell PATH Full pathname of instrumented fuzzershell
14# --afl-data DIR3 DIR3 is the "-o" directory from afl-fuzz
15# -o FILE Write results into FILE
16#
17set AFLBIN {}
18set FUZZERSHELL {}
19set AFLDATA {}
20set OUTFILE {}
21
22proc usage {} {
23 puts stderr "Usage: $::argv0 --afl-bin DIR --fuzzershell PATH\
24 --afl-data DIR -o FILE"
25 exit 1
26}
27proc cmdlineerr {msg} {
28 puts stderr $msg
29 usage
30}
31
32for {set i 0} {$i<[llength $argv]} {incr i} {
33 set x [lindex $argv $i]
34 if {[string index $x 0]!="-"} {cmdlineerr "illegal argument: $x"}
35 set x [string trimleft $x -]
36 incr i
37 if {$i>=[llength $argv]} {cmdlineerr "no argument on --$x"}
38 set a [lindex $argv $i]
39 switch -- $x {
40 afl-bin {set AFLBIN $a}
41 afl-data {set AFLDATA $a}
42 fuzzershell {set FUZZERSHELL $a}
43 o {set OUTFILE $a}
44 default {cmdlineerr "unknown option: --$x"}
45 }
46}
47proc checkarg {varname option} {
48 set val [set ::$varname]
49 if {$val==""} {cmdlineerr "required option missing: --$option"}
50}
51checkarg AFLBIN afl-bin
52checkarg AFLDATA afl-data
53checkarg FUZZERSHELL fuzzershell
54checkarg OUTFILE o
55proc checkexec {x} {
56 if {![file exec $x]} {cmdlineerr "cannot find $x"}
57}
58checkexec $AFLBIN/afl-cmin
59checkexec $AFLBIN/afl-tmin
60checkexec $FUZZERSHELL
61proc checkdir {x} {
62 if {![file isdir $x]} {cmdlineerr "no such directory: $x"}
63}
64checkdir $AFLDATA/queue
65
66proc progress {msg} {
67 puts "******** $msg"
68 flush stdout
69}
70progress "mkdir tmp1 tmp2"
71file mkdir tmp1 tmp2
72progress "copying test cases from $AFLDATA into tmp1..."
73set n 0
74foreach file [glob -nocomplain $AFLDATA/queue/id:*] {
75 incr n
76 file copy $file tmp1/$n
77}
78foreach file [glob -nocomplain $AFLDATA/crash*/id:*] {
79 incr n
80 file copy $file tmp1/$n
81}
82progress "total $n files copied."
83progress "running: $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL"
84exec $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL >&@ stdout
85progress "afl-cmin complete."
86#
87# Experiments show that running afl-tmin is too slow for this application.
88# And it doesn't really make the test cases that much smaller. So let's
89# just skip it.
90#
91# foreach file [glob tmp2/*] {
92# progress "$AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] $FUZZERSHELL"
93# exec $AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] \
94# $FUZZERSHELL >&@ stdout
95# }
96progress "generating final output into $OUTFILE"
97set out [open $OUTFILE wb]
98puts $out "# Test data for use with fuzzershell. Automatically
99# generated using $argv0. This file contains binary data
100#"
101set n 0
102foreach file [glob tmp2/*] {
103 incr n
104 puts -nonewline $out "/****<$n>****/"
105 set in [open $file rb]
106 puts -nonewline $out [read $in]
107 close $in
108}
109close $out
110progress "done. $n test cases written to $OUTFILE"
111progress "clean-up..."
drh6c984152015-04-30 13:06:15 +0000112file delete -force tmp1
113progress "culled test cases left in the tmp2 directory"