/dns_message_checksig
/dns_message_parse
/dns_name_fromtext_target
+/dns_name_fromwire
/dns_rdata_fromtext
/dns_rdata_fromwire_text
/isc_lex_getmastertoken
dns_message_checksig \
dns_message_parse \
dns_name_fromtext_target \
+ dns_name_fromwire \
dns_rdata_fromtext \
dns_rdata_fromwire_text \
isc_lex_getmastertoken \
dns_message_checksig.in \
dns_message_parse.in \
dns_name_fromtext_target.in \
+ dns_name_fromwire.in \
dns_rdata_fromtext.in \
dns_rdata_fromwire_text.in \
isc_lex_getmastertoken.in \
isc_lex_gettoken.in
+dns_name_fromwire_SOURCES = \
+ dns_name_fromwire.c \
+ old.c \
+ old.h
+
TESTS = $(check_PROGRAMS)
if HAVE_FUZZ_LOG_COMPILER
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/ascii.h>
+#include <isc/buffer.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+
+#include "fuzz.h"
+#include "old.h"
+
+bool debug = false;
+
+int
+LLVMFuzzerInitialize(int *argc __attribute__((unused)),
+ char ***argv __attribute__((unused))) {
+ return (0);
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ isc_result_t new_result;
+ isc_result_t old_result;
+ dns_fixedname_t new_fixed;
+ dns_fixedname_t old_fixed;
+ dns_name_t *new_name = dns_fixedname_initname(&new_fixed);
+ dns_name_t *old_name = dns_fixedname_initname(&old_fixed);
+ uint8_t *new_offsets;
+ uint8_t *old_offsets;
+ dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
+ isc_buffer_t new_buf;
+ isc_buffer_t old_buf;
+
+ /*
+ * Output buffers may be partially used or undersized.
+ */
+ if (size > 0) {
+ uint8_t add = *data++;
+ size--;
+ isc_buffer_add(&new_fixed.buffer, add);
+ isc_buffer_add(&old_fixed.buffer, add);
+ }
+
+ /*
+ * timeout faster if we hit a pointer loop
+ */
+ alarm(1);
+
+ /*
+ * We shift forward by half the input data to make an area
+ * that pointers can refer back to.
+ */
+
+ isc_buffer_constinit(&new_buf, data, size);
+ isc_buffer_add(&new_buf, size);
+ isc_buffer_setactive(&new_buf, size);
+ isc_buffer_forward(&new_buf, size / 2);
+ new_result = dns_name_fromwire(new_name, &new_buf, dctx, 0, NULL);
+
+ isc_buffer_constinit(&old_buf, data, size);
+ isc_buffer_add(&old_buf, size);
+ isc_buffer_setactive(&old_buf, size);
+ isc_buffer_forward(&old_buf, size / 2);
+ old_result = old_name_fromwire(old_name, &old_buf, dctx, 0, NULL);
+
+ REQUIRE(new_result == old_result);
+ REQUIRE(dns_name_equal(new_name, old_name));
+ REQUIRE(new_name->labels == old_name->labels);
+
+ new_offsets = new_name->offsets;
+ old_offsets = old_name->offsets;
+ REQUIRE(new_offsets != NULL && old_offsets != NULL);
+ REQUIRE(memcmp(new_offsets, old_offsets, old_name->labels) == 0);
+
+ REQUIRE(new_fixed.buffer.current == old_fixed.buffer.current);
+ REQUIRE(new_fixed.buffer.active == old_fixed.buffer.active);
+ REQUIRE(new_fixed.buffer.used == old_fixed.buffer.used);
+ REQUIRE(new_fixed.buffer.length == old_fixed.buffer.length);
+
+ REQUIRE(new_buf.base == old_buf.base);
+ REQUIRE(new_buf.current == old_buf.current);
+ REQUIRE(new_buf.active == old_buf.active);
+ REQUIRE(new_buf.used == old_buf.used);
+ REQUIRE(new_buf.length == old_buf.length);
+
+ return (0);
+}
--- /dev/null
+\8a0
\ No newline at end of file
--- /dev/null
+î0õw
\ No newline at end of file
--- /dev/null
+0\8f
\ No newline at end of file
--- /dev/null
+\84ÿ
+\8b
\ No newline at end of file
--- /dev/null
+\8dõ
\ No newline at end of file
--- /dev/null
+*
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <isc/ascii.h>
+#include <isc/buffer.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/types.h>
+
+/*
+ */
+
+#include "old.h"
+
+/*
+ * code copied from lib/dns/name.c as of commit
+ * 6967973568fe80b03e1729259f8907ce8792be34
+ */
+
+typedef enum { fw_start = 0, fw_ordinary, fw_newcurrent } fw_state;
+
+#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
+
+#define INIT_OFFSETS(name, var, default_offsets) \
+ if ((name)->offsets != NULL) \
+ var = (name)->offsets; \
+ else \
+ var = (default_offsets);
+
+#define MAKE_EMPTY(name) \
+ do { \
+ name->ndata = NULL; \
+ name->length = 0; \
+ name->labels = 0; \
+ name->attributes.absolute = false; \
+ } while (0)
+
+#define BINDABLE(name) (!name->attributes.readonly && !name->attributes.dynamic)
+
+isc_result_t
+old_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
+ unsigned int options, isc_buffer_t *target) {
+ unsigned char *cdata, *ndata;
+ unsigned int cused; /* Bytes of compressed name data used */
+ unsigned int nused, labels, n, nmax;
+ unsigned int current, new_current, biggest_pointer;
+ bool done;
+ fw_state state = fw_start;
+ unsigned int c;
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ bool downcase;
+ bool seen_pointer;
+
+ /*
+ * Copy the possibly-compressed name at source into target,
+ * decompressing it. Loop prevention is performed by checking
+ * the new pointer against biggest_pointer.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
+ (target == NULL && ISC_BUFFER_VALID(name->buffer)));
+
+ downcase = ((options & DNS_NAME_DOWNCASE) != 0);
+
+ if (target == NULL && name->buffer != NULL) {
+ target = name->buffer;
+ isc_buffer_clear(target);
+ }
+
+ REQUIRE(BINDABLE(name));
+
+ INIT_OFFSETS(name, offsets, odata);
+
+ /*
+ * Make 'name' empty in case of failure.
+ */
+ MAKE_EMPTY(name);
+
+ /*
+ * Initialize things to make the compiler happy; they're not required.
+ */
+ n = 0;
+ new_current = 0;
+
+ /*
+ * Set up.
+ */
+ labels = 0;
+ done = false;
+
+ ndata = isc_buffer_used(target);
+ nused = 0;
+ seen_pointer = false;
+
+ /*
+ * Find the maximum number of uncompressed target name
+ * bytes we are willing to generate. This is the smaller
+ * of the available target buffer length and the
+ * maximum legal domain name length (255).
+ */
+ nmax = isc_buffer_availablelength(target);
+ if (nmax > DNS_NAME_MAXWIRE) {
+ nmax = DNS_NAME_MAXWIRE;
+ }
+
+ cdata = isc_buffer_current(source);
+ cused = 0;
+
+ current = source->current;
+ biggest_pointer = current;
+
+ /*
+ * Note: The following code is not optimized for speed, but
+ * rather for correctness. Speed will be addressed in the future.
+ */
+
+ while (current < source->active && !done) {
+ c = *cdata++;
+ current++;
+ if (!seen_pointer) {
+ cused++;
+ }
+
+ switch (state) {
+ case fw_start:
+ if (c < 64) {
+ offsets[labels] = nused;
+ labels++;
+ if (nused + c + 1 > nmax) {
+ goto full;
+ }
+ nused += c + 1;
+ *ndata++ = c;
+ if (c == 0) {
+ done = true;
+ }
+ n = c;
+ state = fw_ordinary;
+ } else if (c >= 192) {
+ /*
+ * 14-bit compression pointer
+ */
+ if (!dns_decompress_getpermitted(dctx)) {
+ return (DNS_R_DISALLOWED);
+ }
+ new_current = c & 0x3F;
+ state = fw_newcurrent;
+ } else {
+ return (DNS_R_BADLABELTYPE);
+ }
+ break;
+ case fw_ordinary:
+ if (downcase) {
+ c = isc_ascii_tolower(c);
+ }
+ *ndata++ = c;
+ n--;
+ if (n == 0) {
+ state = fw_start;
+ }
+ break;
+ case fw_newcurrent:
+ new_current *= 256;
+ new_current += c;
+ if (new_current >= biggest_pointer) {
+ return (DNS_R_BADPOINTER);
+ }
+ biggest_pointer = new_current;
+ current = new_current;
+ cdata = (unsigned char *)source->base + current;
+ seen_pointer = true;
+ state = fw_start;
+ break;
+ default:
+ FATAL_ERROR("Unknown state %d", state);
+ /* Does not return. */
+ }
+ }
+
+ if (!done) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ name->ndata = (unsigned char *)target->base + target->used;
+ name->labels = labels;
+ name->length = nused;
+ name->attributes.absolute = true;
+
+ isc_buffer_forward(source, cused);
+ isc_buffer_add(target, name->length);
+
+ return (ISC_R_SUCCESS);
+
+full:
+ if (nmax == DNS_NAME_MAXWIRE) {
+ /*
+ * The name did not fit even though we had a buffer
+ * big enough to fit a maximum-length name.
+ */
+ return (DNS_R_NAMETOOLONG);
+ } else {
+ /*
+ * The name might fit if only the caller could give us a
+ * big enough buffer.
+ */
+ return (ISC_R_NOSPACE);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*%
+ * For verifying no functional change in the rewrite of dns_name_fromwire()
+ */
+isc_result_t
+old_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t dctx,
+ unsigned int options, isc_buffer_t *target);
/ascii
/compress
+/dns_name_fromwire
/siphash
AM_CPPFLAGS += \
$(LIBISC_CFLAGS) \
- $(LIBDNS_CFLAGS)
+ $(LIBDNS_CFLAGS) \
+ -I$(top_srcdir)/fuzz
LDADD += \
$(LIBISC_LIBS) \
noinst_PROGRAMS = \
ascii \
compress \
+ dns_name_fromwire \
siphash
+
+dns_name_fromwire_SOURCES = \
+ $(top_builddir)/fuzz/old.c \
+ $(top_builddir)/fuzz/old.h \
+ dns_name_fromwire.c
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/ascii.h>
+#include <isc/buffer.h>
+#include <isc/random.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+
+#include "old.h"
+
+static uint32_t
+old_bench(const uint8_t *data, size_t size) {
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ dns_name_t *name = dns_fixedname_initname(&fixed);
+ dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
+ isc_buffer_t buf;
+ uint32_t count = 0;
+
+ isc_buffer_constinit(&buf, data, size);
+ isc_buffer_add(&buf, size);
+ isc_buffer_setactive(&buf, size);
+
+ while (isc_buffer_consumedlength(&buf) < size) {
+ result = old_name_fromwire(name, &buf, dctx, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_forward(&buf, 1);
+ }
+ count++;
+ }
+ return (count);
+}
+
+static uint32_t
+new_bench(const uint8_t *data, size_t size) {
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ dns_name_t *name = dns_fixedname_initname(&fixed);
+ dns_decompress_t dctx = DNS_DECOMPRESS_PERMITTED;
+ isc_buffer_t buf;
+ uint32_t count = 0;
+
+ isc_buffer_constinit(&buf, data, size);
+ isc_buffer_add(&buf, size);
+ isc_buffer_setactive(&buf, size);
+
+ while (isc_buffer_consumedlength(&buf) < size) {
+ result = dns_name_fromwire(name, &buf, dctx, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_forward(&buf, 1);
+ }
+ count++;
+ }
+ return (count);
+}
+
+static void
+oldnew_bench(const uint8_t *data, size_t size) {
+ isc_time_t t0;
+ isc_time_now_hires(&t0);
+ uint32_t n1 = old_bench(data, size);
+ isc_time_t t1;
+ isc_time_now_hires(&t1);
+ uint32_t n2 = new_bench(data, size);
+ isc_time_t t2;
+ isc_time_now_hires(&t2);
+
+ double t01 = (double)isc_time_microdiff(&t1, &t0);
+ double t12 = (double)isc_time_microdiff(&t2, &t1);
+ printf(" old %u / %f ms; %f / us\n", n1, t01 / 1000.0, n1 / t01);
+ printf(" new %u / %f ms; %f / us\n", n2, t12 / 1000.0, n2 / t12);
+ printf(" old/new %f or %f\n", t01 / t12, t12 / t01);
+}
+
+#define NAMES 1000
+static uint8_t buf[1024 * NAMES];
+
+int
+main(void) {
+ unsigned int p;
+
+ printf("random buffer\n");
+ isc_random_buf(buf, sizeof(buf));
+ oldnew_bench(buf, sizeof(buf));
+
+ p = 0;
+ for (unsigned int name = 0; name < NAMES; name++) {
+ unsigned int start = p;
+ unsigned int prev = p;
+ buf[p++] = 0;
+ for (unsigned int label = 0; label < 127; label++) {
+ unsigned int ptr = prev - start;
+ prev = p;
+ buf[p++] = 1;
+ buf[p++] = 'a';
+ buf[p++] = 0xC0 | (ptr >> 8);
+ buf[p++] = 0xFF & ptr;
+ }
+ }
+ printf("127 compression pointers\n");
+ oldnew_bench(buf, p);
+
+ p = 0;
+ for (unsigned int name = 0; name < NAMES; name++) {
+ for (unsigned int label = 0; label < 127; label++) {
+ buf[p++] = 1;
+ buf[p++] = 'a';
+ }
+ buf[p++] = 0;
+ }
+ printf("127 sequential labels\n");
+ oldnew_bench(buf, p);
+
+ p = 0;
+ for (unsigned int name = 0; name < NAMES; name++) {
+ for (unsigned int label = 0; label < 4; label++) {
+ buf[p++] = 62;
+ for (unsigned int c = 0; c < 62; c++) {
+ buf[p++] = 'a';
+ }
+ }
+ buf[p++] = 0;
+ }
+ printf("4 long sequential labels\n");
+ oldnew_bench(buf, p);
+}