Turn on memory scrubbing when fuzz testing.
[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 # This needs to point to a 'date' that supports %s.
13 DATE=/bin/date
14 BASE_NAME=fuzz-`$DATE +%Y-%m-%d`-$$
15
16 # Directory containing binaries.  Default current directory.
17 BIN_DIR=.
18
19 # Temporary file directory and names.
20 # (had problems with this on cygwin, tried TMP_DIR=./ which worked)
21 TMP_DIR=/tmp
22 if [ "$OSTYPE" == "cygwin" ] ; then
23         TMP_DIR=`cygpath --windows "$TMP_DIR"`
24 fi
25 TMP_FILE=$BASE_NAME.pcap
26 ERR_FILE=$BASE_NAME.err
27
28 # Loop this many times (< 1 loops forever)
29 MAX_PASSES=0
30
31 # Perform a two pass analysis on the capture file?
32 TWO_PASS=
33
34 # These may be set to your liking
35 # Stop the child process, if it's running longer than x seconds
36 MAX_CPU_TIME=900
37 # Stop the child process, if it's using more than y * 1024 bytes
38 MAX_VMEM=500000
39 # Insert z times an error into the capture file (0.02 seems to be a good value to find errors)
40 ERR_PROB=0.02
41 # Trigger an abort if a dissector finds a bug.
42 # Uncomment to enable
43 # Note that if ABORT is enabled there will be no info
44 #  output to stderr about the DISSECTOR_BUG.
45 #  (There'll just be a core-dump).
46 ###export WIRESHARK_ABORT_ON_DISSECTOR_BUG="True"
47
48
49 # To do: add options for file names and limits
50 while getopts ":b:d:e:Pp:" OPTCHAR ; do
51     case $OPTCHAR in
52         b) BIN_DIR=$OPTARG ;;
53         d) TMP_DIR=$OPTARG ;;
54         e) ERR_PROB=$OPTARG ;;
55         p) MAX_PASSES=$OPTARG ;;
56         P) TWO_PASS="-P " ;;
57     esac
58 done
59 shift $(($OPTIND - 1))
60
61 # Tweak the following to your liking.  Editcap must support "-E".
62 TSHARK="$BIN_DIR/tshark"
63 EDITCAP="$BIN_DIR/editcap"
64 CAPINFOS="$BIN_DIR/capinfos"
65
66 # set some limits to the child processes, e.g. stop it if it's running longer then MAX_CPU_TIME seconds
67 # (ulimit is not supported well on cygwin and probably other platforms, e.g. cygwin shows some warnings)
68 ulimit -S -t $MAX_CPU_TIME -v $MAX_VMEM
69 ulimit -c unlimited
70
71 ### usually you won't have to change anything below this line ###
72
73 # TShark arguments (you won't have to change these)
74 # n Disable network object name resolution
75 # V Print a view of the details of the packet rather than a one-line summary of the packet
76 # x Cause TShark to print a hex and ASCII dump of the packet data after printing the summary or details
77 # r Read packet data from the following infile
78 TSHARK_ARGS="${TWO_PASS}-nVxr"
79
80 NOTFOUND=0
81 for i in "$TSHARK" "$EDITCAP" "$CAPINFOS" "$DATE" "$TMP_DIR" ; do
82     if [ ! -x $i ]; then
83         echo "Couldn't find $i"
84         NOTFOUND=1
85     fi
86 done
87 if [ $NOTFOUND -eq 1 ]; then
88     exit 1
89 fi
90
91 # Make sure we have a valid test set
92 FOUND=0
93 for CF in "$@" ; do
94     if [ "$OSTYPE" == "cygwin" ] ; then
95         CF=`cygpath --windows "$CF"`
96     fi
97     "$CAPINFOS" "$CF" > /dev/null 2>&1 && FOUND=1
98     if [ $FOUND -eq 1 ] ; then break ; fi
99 done
100
101 if [ $FOUND -eq 0 ] ; then
102     cat <<FIN
103 Error: No valid capture files found.
104
105 Usage: `basename $0` [-p passes] [-d work_dir] [-P ] [-e error probability] capture file 1 [capture file 2]...
106 FIN
107     exit 1
108 fi
109
110 HOWMANY="forever"
111 if [ $MAX_PASSES -gt 0 ]; then
112         HOWMANY="$MAX_PASSES passes"
113 fi
114 echo "Running $TSHARK with args: $TSHARK_ARGS ($HOWMANY)"
115 echo ""
116
117 # Clean up on <ctrl>C, etc
118 trap "rm -f $TMP_DIR/$TMP_FILE $TMP_DIR/$ERR_FILE; echo ""; exit 0" HUP INT TERM
119
120 # Iterate over our capture files.
121 PASS=0
122 while [ $PASS -lt $MAX_PASSES -o $MAX_PASSES -lt 1 ] ; do
123     PASS=`expr $PASS + 1`
124     echo "Starting pass $PASS:"
125     RUN=0
126
127     for CF in "$@" ; do
128         RUN=$(( $RUN + 1 ))
129         if [ $(( $RUN % 50 )) -eq 0 ] ; then
130             echo "    [Pass $PASS]"
131         fi
132         if [ "$OSTYPE" == "cygwin" ] ; then
133             CF=`cygpath --windows "$CF"`
134         fi
135     echo -n "    $CF: "
136
137     "$CAPINFOS" "$CF" > /dev/null 2> $TMP_DIR/$ERR_FILE
138     RETVAL=$?
139     if [ $RETVAL -eq 0 ] ; then
140         # have a valid file
141         rm -f $TMP_DIR/$ERR_FILE
142     elif [ $RETVAL -eq 1 ] ; then
143         echo "Not a valid capture file"
144         rm -f $TMP_DIR/$ERR_FILE
145         continue
146     else
147         echo ""
148         echo " ERROR"
149         echo -e "Processing failed.  Capture info follows:\n"
150         echo "  Input file: $CF"
151         echo -e "stderr follows:\n"
152         cat $TMP_DIR/$ERR_FILE
153         exit 1
154     fi
155
156     DISSECTOR_BUG=0
157
158     "$EDITCAP" -E $ERR_PROB "$CF" $TMP_DIR/$TMP_FILE > /dev/null 2>&1
159     if [ $? -ne 0 ] ; then
160         "$EDITCAP" -E $ERR_PROB -T ether "$CF" $TMP_DIR/$TMP_FILE \
161         > /dev/null 2>&1
162         if [ $? -ne 0 ] ; then
163         echo "Invalid format for editcap"
164         continue
165         fi
166     fi
167
168     export WIRESHARK_DEBUG_SCRUB_MEMORY=1
169     export WIRESHARK_DEBUG_SE_USE_CANARY=1
170     "$TSHARK" $TSHARK_ARGS $TMP_DIR/$TMP_FILE \
171         > /dev/null 2> $TMP_DIR/$ERR_FILE
172     RETVAL=$?
173     # Uncomment the next two lines to enable dissector bug
174     # checking.
175     #grep -i "dissector bug" $TMP_DIR/$ERR_FILE \
176     #    > /dev/null 2>&1 && DISSECTOR_BUG=1
177     if [ $RETVAL -ne 0 -o $DISSECTOR_BUG -ne 0 ] ; then
178             echo ""
179         echo " ERROR"
180         echo -e "Processing failed.  Capture info follows:\n"
181         echo "  Output file: $TMP_DIR/$TMP_FILE"
182         if [ $DISSECTOR_BUG -ne 0 ] ; then
183         echo -e "stderr follows:\n"
184         cat $TMP_DIR/$ERR_FILE
185         fi
186         exit 1
187     fi
188     echo " OK"
189         rm -f $TMP_DIR/$TMP_FILE $TMP_DIR/$ERR_FILE
190     done
191 done
192