]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
dns_rdata_fromwire_text fuzzer
authorMark Andrews <marka@isc.org>
Fri, 1 Mar 2019 02:46:48 +0000 (13:46 +1100)
committerMark Andrews <marka@isc.org>
Thu, 9 May 2019 00:30:40 +0000 (20:30 -0400)
Fuzz input to dns_rdata_fromwire(). Then convert the result
to text, back to wire format, to multiline text, and back to wire
format again, checking for consistency throughout the sequence.

fuzz/.gitignore
fuzz/Makefile.in
fuzz/dns_rdata_fromwire_text.c [new file with mode: 0644]
fuzz/dns_rdata_fromwire_text.in/cdnskey [new file with mode: 0644]
fuzz/dns_rdata_fromwire_text.in/smimea [new file with mode: 0644]
fuzz/dns_rdata_fromwire_text.in/sshfp [new file with mode: 0644]
util/copyrights

index 5148e33eac38b965d712fa5ed309ac6e172150cd..8edb50ea2f34f5e0e420c9090ecb5e4a52efc309 100644 (file)
@@ -1,3 +1,4 @@
 /*.dSYM/
 dns_name_fromtext_target
+dns_rdata_fromwire_text
 /*.out/
index 6757f17910e83e20456cda3cb27f3270dad50946..84ad6c1ebf93936930ff8cb151d7be82551e82ad 100644 (file)
@@ -17,10 +17,11 @@ DNSDEPLIBS =        ../lib/dns/libdns.@A@
 LIBS =         @LIBS@
 
 OBJS =         main.@O@
-SRCS =         main.c dns_name_fromtext_target.c
+SRCS =         main.c dns_name_fromtext_target.c dns_rdata_fromwire_text.c
 
 SUBDIRS =
-TARGETS =      dns_name_fromtext_target@EXEEXT@
+TARGETS =      dns_name_fromtext_target@EXEEXT@ \
+               dns_rdata_fromwire_text@EXEEXT@
 
 @BIND9_MAKE_RULES@
 
@@ -28,6 +29,10 @@ dns_name_fromtext_target@EXEEXT@: dns_name_fromtext_target.@O@ main.@O@ ${ISCDEP
        ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
                dns_name_fromtext_target.@O@ main.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
 
+dns_rdata_fromwire_text@EXEEXT@: dns_rdata_fromwire_text.@O@ main.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+       ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+               dns_rdata_fromwire_text.@O@ main.@O@ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
 check: ${TARGETS}
        for fuzzer in ${TARGETS}; do \
                ./$${fuzzer} ; \
diff --git a/fuzz/dns_rdata_fromwire_text.c b/fuzz/dns_rdata_fromwire_text.c
new file mode 100644 (file)
index 0000000..628c71e
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/compress.h>
+#include <dns/master.h>
+#include <dns/rdata.h>
+#include <dns/rdatatype.h>
+
+#define CHECK(x) ({ if ((result = (x)) != ISC_R_SUCCESS) goto done; })
+
+/*
+ * Fuzz input to dns_rdata_fromwire(). Then convert the result
+ * to text, back to wire format, to multiline text, and back to wire
+ * format again, checking for consistency throughout the sequence.
+ */
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static void
+nullmsg(dns_rdatacallbacks_t *cb, const char *fmt, ...) {
+       va_list ap;
+
+       UNUSED(cb);
+       UNUSED(fmt);
+       UNUSED(ap);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+       char totext[1024];
+       dns_compress_t cctx;
+       dns_decompress_t dctx;
+       dns_rdatatype_t rdtype;
+       dns_rdataclass_t rdclass;
+       dns_rdatatype_t typelist[256] = { 1000 };       /* unknown */
+       dns_rdataclass_t classlist[] = { dns_rdataclass_in,
+                                        dns_rdataclass_hs,
+                                        dns_rdataclass_ch,
+                                        dns_rdataclass_any,
+                                        60 };
+       dns_rdata_t rdata1 = DNS_RDATA_INIT,
+                   rdata2 = DNS_RDATA_INIT,
+                   rdata3 = DNS_RDATA_INIT;
+       dns_rdatacallbacks_t callbacks;
+       isc_buffer_t source, target;
+       isc_lex_t *lex = NULL;
+       isc_lexspecials_t specials;
+       isc_mem_t *mctx = NULL;
+       isc_result_t result;
+       unsigned char fromtext[1024];
+       unsigned char fromwire[1024];
+       unsigned char towire[1024];
+       unsigned int classes = (sizeof(classlist)/sizeof(classlist[0]));
+       unsigned int types = 1, flags, t;
+
+       if (size < 2) {
+               goto done;
+       }
+
+       /*
+        * Append known types to list.
+        */
+       for (t = 1; t <= 0x10000; t++) {
+               char typebuf[256];
+               if (dns_rdatatype_ismeta(t)) {
+                       continue;
+               }
+               dns_rdatatype_format(t, typebuf, sizeof(typebuf));
+               if (strncmp(typebuf, "TYPE", 4) != 0) {
+                       /* Assert when we need to grow typelist. */
+                       assert(types < sizeof(typelist)/sizeof(typelist[0]));
+                       typelist[types++] = t;
+               }
+       }
+
+       /*
+        * Random type and class from a limited set.
+        */
+       rdtype = typelist[(*data++) % types]; size--;
+       rdclass = classlist[(*data++) % classes]; size--;
+
+       CHECK(isc_mem_create(0, 0, &mctx));
+
+       CHECK(isc_lex_create(mctx, 64, &lex));
+       memset(specials, 0, sizeof(specials));
+       specials[0] = 1;
+       specials['('] = 1;
+       specials[')'] = 1;
+       specials['"'] = 1;
+       isc_lex_setspecials(lex, specials);
+       isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+
+       dns_rdatacallbacks_init(&callbacks);
+       callbacks.warn = callbacks.error = nullmsg;
+
+       dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
+
+       isc_buffer_constinit(&source, data, size);
+       isc_buffer_add(&source, size);
+       isc_buffer_setactive(&source, size);
+
+       isc_buffer_init(&target, fromwire, sizeof(fromwire));
+
+       /*
+        * Reject invalid rdata.
+        */
+       CHECK(dns_rdata_fromwire(&rdata1, rdclass, rdtype, &source, &dctx,
+                                0, &target));
+
+       /*
+        * Convert to text from wire.
+        */
+       isc_buffer_init(&target, totext, sizeof(totext));
+       result = dns_rdata_totext(&rdata1, NULL, &target);
+       assert(result == ISC_R_SUCCESS);
+
+       /*
+        * Convert to wire from text.
+        */
+       isc_buffer_constinit(&source, totext, isc_buffer_usedlength(&target));
+       isc_buffer_add(&source, isc_buffer_usedlength(&target));
+       CHECK(isc_lex_openbuffer(lex, &source));
+
+       isc_buffer_init(&target, fromtext, sizeof(fromtext));
+       result = dns_rdata_fromtext(&rdata2, rdclass, rdtype, lex,
+                                   dns_rootname, 0, mctx, &target,
+                                   &callbacks);
+       assert(result == ISC_R_SUCCESS);
+       assert(rdata2.length == size);
+       assert(!memcmp(rdata2.data, data, size));
+
+       /*
+        * Convert to multi-line text from wire.
+        */
+       isc_buffer_init(&target, totext, sizeof(totext));
+       flags = dns_master_styleflags(&dns_master_style_default);
+       result = dns_rdata_tofmttext(&rdata1, dns_rootname, flags,
+                                    80 - 32, 4, "\n", &target);
+       assert(result == ISC_R_SUCCESS);
+
+       /*
+        * Convert to wire from text.
+        */
+       isc_buffer_constinit(&source, totext, isc_buffer_usedlength(&target));
+       isc_buffer_add(&source, isc_buffer_usedlength(&target));
+       CHECK(isc_lex_openbuffer(lex, &source));
+
+       isc_buffer_init(&target, fromtext, sizeof(fromtext));
+       result = dns_rdata_fromtext(&rdata3, rdclass, rdtype, lex,
+                                   dns_rootname, 0, mctx, &target,
+                                   &callbacks);
+       assert(result == ISC_R_SUCCESS);
+       assert(rdata3.length == size);
+       assert(!memcmp(rdata3.data, data, size));
+
+       /*
+        * Convert rdata back to wire.
+        */
+       CHECK(dns_compress_init(&cctx, -1, mctx));
+       dns_compress_setsensitive(&cctx, true);
+       isc_buffer_init(&target, towire, sizeof(towire));
+       result = dns_rdata_towire(&rdata1, &cctx, &target);
+       dns_compress_invalidate(&cctx);
+       assert(result == ISC_R_SUCCESS);
+       assert(target.used == size);
+       assert(!memcmp(target.base, data, size));
+
+ done:
+       if (lex != NULL) {
+               isc_lex_destroy(&lex);
+       }
+       if (lex != NULL) {
+               isc_mem_detach(&mctx);
+       }
+       return (0);
+}
diff --git a/fuzz/dns_rdata_fromwire_text.in/cdnskey b/fuzz/dns_rdata_fromwire_text.in/cdnskey
new file mode 100644 (file)
index 0000000..9eb47d5
Binary files /dev/null and b/fuzz/dns_rdata_fromwire_text.in/cdnskey differ
diff --git a/fuzz/dns_rdata_fromwire_text.in/smimea b/fuzz/dns_rdata_fromwire_text.in/smimea
new file mode 100644 (file)
index 0000000..528472d
--- /dev/null
@@ -0,0 +1 @@
+\85-Òe\9c<
\ No newline at end of file
diff --git a/fuzz/dns_rdata_fromwire_text.in/sshfp b/fuzz/dns_rdata_fromwire_text.in/sshfp
new file mode 100644 (file)
index 0000000..b3007cd
--- /dev/null
@@ -0,0 +1 @@
+|\87°|\ f8
\ No newline at end of file
index 0744c9006b0315c3002880eedb65bb911aa604ac..f1e450d3005c33338140e0dd47beadb96a4755ef 100644 (file)
 ./docutil/patch-db2latex-nested-param-bug      X       2007,2018,2019
 ./docutil/patch-db2latex-xsltproc-title-bug    X       2007,2018,2019
 ./fuzz/dns_name_fromtext_target.c              C       2018,2019
+./fuzz/dns_rdata_fromwire_text.c               C       2019
 ./fuzz/fuzz.h                                  C       2018,2019
 ./fuzz/main.c                                  C       2018,2019
 ./install-sh                                   X       1998,1999,2000,2001,2018,2019