Let the user set the working directory and number of passes from the command
[obnox/wireshark/wip.git] / tools / fuzz-test.sh
1 #!/bin/bash
2 #
3 # $Id$
4
5 # Fuzz-testing script for TShark
6 #
7 # This script uses Editcap to add random errors ("fuzz") to a set of
8 # capture files specified on the command line.  It runs TShark on
9 # each fuzzed file and checks for errors.  The files are processed
10 # repeatedly until an error is found.
11
12 # Tweak the following to your liking.  Editcap must support "-E".
13 TSHARK=./tshark
14 EDITCAP=./editcap
15 CAPINFOS=./capinfos
16
17 # This needs to point to a 'date' that supports %s.
18 DATE=/bin/date
19
20 # Temporary file directory and names.
21 # (had problems with this on cygwin, tried TMP_DIR=./ which worked)
22 TMP_DIR=/tmp
23 TMP_FILE=fuzz-test-`$DATE +%Y-%m-%d`-$$.pcap
24 ERR_FILE=fuzz-err-`$DATE +%Y-%m-%d`-$$.txt
25
26 # Loop this many times (< 1 loops forever)
27 MAX_PASSES=0
28
29 # These may be set to your liking
30 # Stop the child process, if it's running longer than x seconds
31 MAX_CPU_TIME=900
32 # Stop the child process, if it's using more than y * 1024 bytes
33 MAX_VMEM=500000
34 # Insert z times an error into the capture file (0.02 seems to be a good value to find errors)
35 ERR_PROB=0.02
36 # Trigger an abort if a dissector finds a bug.
37 # Uncomment to disable
38 WIRESHARK_ABORT_ON_DISSECTOR_BUG="True"
39
40
41 # To do: add options for file names and limits
42 while getopts ":d:p:" OPTCHAR ; do
43         case $OPTCHAR in
44                 d) TMP_DIR=$OPTARG ;;
45                 p) MAX_PASSES=$OPTARG ;;
46         esac
47 done
48 shift $(($OPTIND - 1))
49
50 # set some limits to the child processes, e.g. stop it if it's running longer then MAX_CPU_TIME seconds
51 # (ulimit is not supported well on cygwin and probably other platforms, e.g. cygwin shows some warnings)
52 ulimit -S -t $MAX_CPU_TIME -v $MAX_VMEM
53 ulimit -c unlimited
54
55 ### usually you won't have to change anything below this line ###
56
57 # TShark arguments (you won't have to change these)
58 # n Disable network object name resolution
59 # V Print a view of the details of the packet rather than a one-line summary of the packet
60 # x Cause TShark to print a hex and ASCII dump of the packet data after printing the summary or details
61 # r Read packet data from the following infile
62 TSHARK_ARGS="-nVxr"
63
64 NOTFOUND=0
65 for i in "$TSHARK" "$EDITCAP" "$CAPINFOS" "$DATE" "$TMP_DIR" ; do
66         if [ ! -x $i ]; then
67                 echo "Couldn't find $i"
68                 NOTFOUND=1
69         fi
70 done
71 if [ $NOTFOUND -eq 1 ]; then
72         exit 1
73 fi
74
75 # Make sure we have a valid test set
76 FOUND=0
77 for CF in "$@" ; do
78     "$CAPINFOS" "$CF" > /dev/null 2>&1 && FOUND=1
79     if [ $FOUND -eq 1 ] ; then break ; fi
80 done
81
82 if [ $FOUND -eq 0 ] ; then
83     cat <<FIN
84 Error: No valid capture files found.
85
86 Usage: `basename $0` [-p passes] [-d work_dir] capture file 1 [capture file 2]...
87 FIN
88     exit 1
89 fi
90
91 HOWMANY="forever"
92 if [ $MAX_PASSES -gt 0 ]; then
93         HOWMANY="$MAX_PASSES passes"
94 fi
95 echo "Running $TSHARK with args: $TSHARK_ARGS ($HOWMANY)"
96 echo ""
97
98 # Not yet - properly handle empty filenames
99 #trap "rm $TMP_DIR/$TMP_FILE $TMP_DIR/$FUZZ_FILE; exit 1" 1 2 15
100
101 # Iterate over our capture files.
102 PASS=0
103 while [ $PASS -lt $MAX_PASSES -o $MAX_PASSES -lt 1 ] ; do
104     PASS=`expr $PASS + 1`
105     echo "Pass $PASS:"
106
107     for CF in "$@" ; do
108         echo -n "    $CF: "
109
110         "$CAPINFOS" "$CF" > /dev/null 2>&1
111         if [ $? -ne 0 ] ; then
112             echo "Not a valid capture file"
113             continue
114         fi
115
116         DISSECTOR_BUG=0
117
118         "$EDITCAP" -E $ERR_PROB "$CF" $TMP_DIR/$TMP_FILE > /dev/null 2>&1
119         if [ $? -ne 0 ] ; then
120             "$EDITCAP" -E $ERR_PROB -T ether "$CF" $TMP_DIR/$TMP_FILE \
121                 > /dev/null 2>&1
122             if [ $? -ne 0 ] ; then
123                 echo "Invalid format for editcap"
124                 continue
125             fi
126         fi
127
128         "$TSHARK" $TSHARK_ARGS $TMP_DIR/$TMP_FILE \
129                 > /dev/null 2> $TMP_DIR/$ERR_FILE
130         RETVAL=$?
131         grep -i "dissector bug" $TMP_DIR/$ERR_FILE \
132             > /dev/null 2>&1 && DISSECTOR_BUG=1
133         if [ $RETVAL -ne 0 -o $DISSECTOR_BUG -ne 0 ] ; then
134             FUZZ_FILE="fuzz-`$DATE +%Y-%m-%d`-$$.pcap"
135             echo ""
136             echo " ERROR"
137             echo -e "Processing failed.  Capture info follows:\n"
138             mv $TMP_DIR/$TMP_FILE $TMP_DIR/$FUZZ_FILE
139             echo "  Output file: $TMP_DIR/$FUZZ_FILE"
140             if [ $DISSECTOR_BUG -ne 0 ] ; then
141                 echo -e "stderr follows:\n"
142                 cat $TMP_DIR/$ERR_FILE
143             fi
144             exit 1
145         fi
146         echo " OK"
147         rm -f $TMP_DIR/$TMP_FILE $TMP_DIR/$ERR_FILE
148     done
149 done
150