We recently added fuzz testing to Ethereal's automated build system.  I
tried out the script we're using on tcpdump and it turned up a bug in
util.c.  Attached are:

  - A patch for util.c:print_unknown_data() that makes sure a negative
    length isn't passed to hex_print().

  - A capture file that triggers the bug in the current daily build.

  - The fuzz testing script that created the capture.  It is based on
    "fuzz-test.sh" from the Ethereal distribution and requires a recent
    version of editcap.

--- ../tcpdump-2005.06.09.orig/util.c	2005-05-06 03:26:45.000000000 -0500
+++ util.c	2005-06-12 14:04:13.520867529 -0500
@@ -244,6 +244,8 @@
 {
 	if (snapend - cp < len)
 		len = snapend - cp;
+	if (len < 0)
+		return(0);	/* XXX - Should we print an error here? */
         hex_print(ident,cp,len);
 	return(1); /* everything is ok */
 }
#!/bin/bash
#
# $Id$

# Fuzz testing script for tcpdump
#
# By Gerald Combs <[EMAIL PROTECTED]> and Ulf Lamping <[EMAIL PROTECTED]>
#
# This script uses Ethereal's Editcap utility to add random errors
# ("fuzz") to a set of capture files specified on the command line.
# It runs tcpdump on each fuzzed file and checks for errors.  The
# files are processed repeatedly until an error is found.

# Tweak the following to your liking.  Editcap must support "-E".
# This feature is present in Ethereal 0.10.11 and later.
TCPDUMP=./tcpdump
EDITCAP=editcap
CAPINFOS=capinfos

# This needs to point to a 'date' that supports %s.
DATE=/bin/date

# Where our temp files are saved (editcap.out and stderr.out)
# Cygwin user may wish to use "TMP_DIR=./".
TMP_DIR=/tmp

# These may be set to your liking
# Stop the child process, if it's running longer than x seconds
MAX_CPU_TIME=900
# Stop the child process, if it's using more than y * 1024 bytes
MAX_VMEM=500000
# Insert z times an error into the capture file (0.02 seems to be a
# good value to find errors)
ERR_PROB=0.02

# set some limits to the child processes, e.g. stop it if it's running
# longer then MAX_CPU_TIME seconds
# (ulimit is not supported well on cygwin and probably other platforms,
# e.g. cygwin shows some warnings)
ulimit -S -t $MAX_CPU_TIME -v $MAX_VMEM

### usually you won't have to change anything below this line ###

# Tcpdump arguments (you won't have to change these)
# vvv Maximum verbosity
# n   Disable network object name resolution
# r   Read packet data from the following infile
TCPDUMP_ARGS="-vvv -nr"

# Make sure we have a valid test set
FOUND=0
for CF in "$@" ; do
    "$CAPINFOS" "$CF" > /dev/null 2>&1 && FOUND=1
    if [ $FOUND -eq 1 ] ; then break ; fi
done

if [ $FOUND -eq 0 ] ; then
    cat <<FIN
Error: No valid capture files found.

Usage: `basename $0` capture file 1 [capture file 2]...
FIN
    exit 1
fi

echo "Running $TCPDUMP with args: $TCPDUMP_ARGS"
echo ""

# Iterate over our capture files.
PASS=0
while [ 1 ] ; do
    PASS=`expr $PASS + 1`
    echo "Pass $PASS:"

    for CF in "$@" ; do
        echo -n "    $CF: "

        "$CAPINFOS" "$CF" > /dev/null 2>&1
        if [ $? -ne 0 ] ; then
            echo "Not a valid capture file"
            continue
        fi

        DISSECTOR_BUG=0

        "$EDITCAP" -E $ERR_PROB "$CF" $TMP_DIR/editcap.out > /dev/null 2>&1
        if [ $? -ne 0 ] ; then
            "$EDITCAP" -E $ERR_PROB -T ether "$CF" $TMP_DIR/editcap.out > 
/dev/null 2>&1
            if [ $? -ne 0 ] ; then
                echo "Invalid format for editcap"
                continue
            fi
        fi

        "$TCPDUMP" $TCPDUMP_ARGS $TMP_DIR/editcap.out \
                > /dev/null 2> $TMP_DIR/stderr.out
        RETVAL=$?
        grep -i "dissector bug" $TMP_DIR/stderr.out \
            > /dev/null 2>&1 && DISSECTOR_BUG=1
        # XXX - Tcpdump had trouble reading some files that editcap generated.
        # We need to handle this better than checking for a return value > 1.
        if [ $RETVAL -gt 1 -o $DISSECTOR_BUG -ne 0 ] ; then
            SECS=`$DATE +%s`
            echo " ERROR"
            echo -e "Processing failed.  Capture info follows:\n"
            mv $TMP_DIR/editcap.out $TMP_DIR/editcap.$SECS.pcap
            echo "  Output file: $TMP_DIR/editcap.$SECS.pcap"
            if [ $DISSECTOR_BUG -ne 0 ] ; then
                echo -e "stderr follows:\n"
                cat $TMP_DIR/stderr.out
            fi
            exit 1
        fi
        echo " OK"
    done
done

-
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.

Reply via email to