]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_9] add a "wire_test -d" option to read raw binary data
authorEvan Hunt <each@isc.org>
Mon, 10 Aug 2015 21:45:05 +0000 (14:45 -0700)
committerEvan Hunt <each@isc.org>
Mon, 10 Aug 2015 21:45:05 +0000 (14:45 -0700)
4169. [test] Added a 'wire_test -d' option to read input as
raw binary data, for use as a fuzzing harness.
[RT #40312]

CHANGES
bin/tests/Makefile.in
bin/tests/fromhex.pl [new file with mode: 0644]
bin/tests/wire_test.c

diff --git a/CHANGES b/CHANGES
index c511863ba3be5c0dc334d7a3698090e3bb3fec4a..83b9276708a97bdfb641c4857c39e5f3adfc5559 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4169.  [test]          Added a 'wire_test -d' option to read input as
+                       raw binary data, for use as a fuzzing harness.
+                       [RT #40312]
+
 4168.  [security]      A buffer accounting error could trigger an
                        assertion failure when parsing certain malformed
                        DNSSEC keys. (CVE-2015-5722) [RT #40212]
index 315cccfb0c09be312608d1df1e3865082f1465fa..43fa42c97608d357a9449b4d8e6ef2e174e0fcab 100644 (file)
@@ -49,7 +49,7 @@ SUBDIRS =     atomic db dst master mem hashes names net rbt resolver \
 # cfg_test is needed for regenerating doc/misc/options
 
 # Alphabetically
-TARGETS =      cfg_test@EXEEXT@
+TARGETS =      cfg_test@EXEEXT@ wire_test@EXEEXT@
 
 # All the other tests are optional and not built by default.
 
@@ -93,7 +93,7 @@ XTARGETS =    adb_test@EXEEXT@ \
                zone_test@EXEEXT@
 
 # Alphabetically
-SRCS =         cfg_test.c ${XSRCS}
+SRCS =         cfg_test.c wire_test.c ${XSRCS}
 
 XSRCS =                adb_test.c \
                byaddr_test.c \
diff --git a/bin/tests/fromhex.pl b/bin/tests/fromhex.pl
new file mode 100644 (file)
index 0000000..8099602
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# Converts hex ascii into raw data.
+# (This can be used, for example, to construct input for "wire_data -d".)
+
+require 5.006.001;
+
+use strict;
+use IO::File;
+
+sub usage {
+    print ("Usage: packet.pl [file]\n");
+    exit 1;
+}
+
+my $file = "STDIN";
+if (@ARGV >= 1) {
+    my $filename = shift @ARGV;
+    open FH, "<$filename" or die "$filename: $!";
+    $file = "FH";
+}
+
+my $input = "";
+while (defined(my $line = <$file>) ) {
+    chomp $line;
+    $line =~ s/#.*$//;
+    $input .= $line;
+}
+
+$input =~ s/\s+//g;
+my $data = pack("H*", $input);
+my $len = length $data;
+
+binmode(STDOUT);
+print($data);
+exit(0);
index af0c6f7fbf1d3606594085a8b74962e0b69b4710..7362c6f3ffde6272a230d2dbe62b9b1f70e3eb0e 100644 (file)
@@ -58,18 +58,19 @@ fromhex(char c) {
        else if (c >= 'A' && c <= 'F')
                return (c - 'A' + 10);
 
-       printf("bad input format: %02x\n", c);
+       fprintf(stderr, "bad input format: %02x\n", c);
        exit(3);
        /* NOTREACHED */
 }
 
 static void
 usage(void) {
-       fprintf(stderr, "wire_test [-p] [-b] [-s] [-r]\n");
-       fprintf(stderr, "\t-p\tPreserve order of the records in messages\n");
+       fprintf(stderr, "wire_test [-b] [-d] [-p] [-r] [-s] [filename]\n");
        fprintf(stderr, "\t-b\tBest-effort parsing (ignore some errors)\n");
-       fprintf(stderr, "\t-s\tPrint memory statistics\n");
+       fprintf(stderr, "\t-d\tRead input as raw binary data\n");
+       fprintf(stderr, "\t-p\tPreserve order of the records in messages\n");
        fprintf(stderr, "\t-r\tAfter parsing, re-render the message\n");
+       fprintf(stderr, "\t-s\tPrint memory statistics\n");
        fprintf(stderr, "\t-t\tTCP mode - ignore the first 2 bytes\n");
 }
 
@@ -85,25 +86,29 @@ main(int argc, char *argv[]) {
        unsigned char b[64 * 1024];
        char s[4000];
        isc_boolean_t tcp = ISC_FALSE;
+       isc_boolean_t rawdata = ISC_FALSE;
        int ch;
 
        mctx = NULL;
        RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
 
-       while ((ch = isc_commandline_parse(argc, argv, "pbsrt")) != -1) {
+       while ((ch = isc_commandline_parse(argc, argv, "bdprst")) != -1) {
                switch (ch) {
-                       case 'p':
-                               parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
-                               break;
                        case 'b':
                                parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
                                break;
-                       case 's':
-                               printmemstats = ISC_TRUE;
+                       case 'd':
+                               rawdata = ISC_TRUE;
+                               break;
+                       case 'p':
+                               parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
                                break;
                        case 'r':
                                dorender = ISC_TRUE;
                                break;
+                       case 's':
+                               printmemstats = ISC_TRUE;
+                               break;
                        case 't':
                                tcp = ISC_TRUE;
                                break;
@@ -116,10 +121,10 @@ main(int argc, char *argv[]) {
        argc -= isc_commandline_index;
        argv += isc_commandline_index;
 
-       if (argc > 1) {
-               f = fopen(argv[1], "r");
+       if (argc >= 1) {
+               f = fopen(argv[0], "r");
                if (f == NULL) {
-                       printf("fopen failed\n");
+                       fprintf(stderr, "%s: fopen failed\n", argv[0]);
                        exit(1);
                }
                need_close = ISC_TRUE;
@@ -127,36 +132,42 @@ main(int argc, char *argv[]) {
                f = stdin;
 
        bp = b;
-       while (fgets(s, sizeof(s), f) != NULL) {
-               rp = s;
-               wp = s;
-               len = 0;
-               while (*rp != '\0') {
-                       if (*rp == '#')
+       if (rawdata) {
+               while (fread(bp, 1, 1, f) != 0)
+                       bp++;
+       } else {
+               while (fgets(s, sizeof(s), f) != NULL) {
+                       rp = s;
+                       wp = s;
+                       len = 0;
+                       while (*rp != '\0') {
+                               if (*rp == '#')
+                                       break;
+                               if (*rp != ' ' && *rp != '\t' &&
+                                   *rp != '\r' && *rp != '\n') {
+                                       *wp++ = *rp;
+                                       len++;
+                               }
+                               rp++;
+                       }
+                       if (len == 0U)
                                break;
-                       if (*rp != ' ' && *rp != '\t' &&
-                           *rp != '\r' && *rp != '\n') {
-                               *wp++ = *rp;
-                               len++;
+                       if (len % 2 != 0U) {
+                               fprintf(stderr, "bad input format: %lu\n",
+                                      (unsigned long)len);
+                               exit(1);
+                       }
+                       if (len > sizeof(b) * 2) {
+                               fprintf(stderr, "input too long\n");
+                               exit(2);
+                       }
+                       rp = s;
+                       for (i = 0; i < len; i += 2) {
+                               n = fromhex(*rp++);
+                               n *= 16;
+                               n += fromhex(*rp++);
+                               *bp++ = n;
                        }
-                       rp++;
-               }
-               if (len == 0U)
-                       break;
-               if (len % 2 != 0U) {
-                       printf("bad input format: %lu\n", (unsigned long)len);
-                       exit(1);
-               }
-               if (len > sizeof(b) * 2) {
-                       printf("input too long\n");
-                       exit(2);
-               }
-               rp = s;
-               for (i = 0; i < len; i += 2) {
-                       n = fromhex(*rp++);
-                       n *= 16;
-                       n += fromhex(*rp++);
-                       *bp++ = n;
                }
        }
 
@@ -169,13 +180,13 @@ main(int argc, char *argv[]) {
                        unsigned int len;
 
                        if (p + 2 > bp) {
-                               printf("premature end of packet\n");
+                               fprintf(stderr, "premature end of packet\n");
                                exit(1);
                        }
                        len = p[0] << 8 | p[1];
 
                        if (p + 2 + len > bp) {
-                               printf("premature end of packet\n");
+                               fprintf(stderr, "premature end of packet\n");
                                exit(1);
                        }
                        isc_buffer_init(&source, p + 2, len);