aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar DavidKorczynski <david@adalogics.com>2021-07-05 17:39:51 +0100
committerGravatar GitHub <noreply@github.com>2021-07-05 17:39:51 +0100
commitd6a3b1cac66ca5dc0356cb7219d3f9f0697c4f29 (patch)
tree6258d994d35bfe4c0e07522f4e42f6539ee9842a
parent64370814b47e93addc215d8c1deaaccd544d4212 (diff)
dnsmasq: new fuzzing set up and fuzzers. (#5996)
* dnsmasq: new fuzzing set up and fuzzers. * remove old util fuzzer from dockerfile.
-rw-r--r--projects/dnsmasq/Dockerfile5
-rwxr-xr-xprojects/dnsmasq/build.sh29
-rw-r--r--projects/dnsmasq/fuzz_auth.c72
-rw-r--r--projects/dnsmasq/fuzz_dhcp.c87
-rw-r--r--projects/dnsmasq/fuzz_dhcp6.c83
-rw-r--r--projects/dnsmasq/fuzz_header.h579
-rw-r--r--projects/dnsmasq/fuzz_patch.patch170
-rw-r--r--projects/dnsmasq/fuzz_rfc1035.c271
-rw-r--r--projects/dnsmasq/fuzz_util.c66
-rw-r--r--projects/dnsmasq/fuzz_util.cpp63
10 files changed, 1356 insertions, 69 deletions
diff --git a/projects/dnsmasq/Dockerfile b/projects/dnsmasq/Dockerfile
index 3d9539e9..6ab50ce2 100644
--- a/projects/dnsmasq/Dockerfile
+++ b/projects/dnsmasq/Dockerfile
@@ -19,4 +19,7 @@ RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone --depth 1 git://thekelleys.org.uk/dnsmasq.git dnsmasq
WORKDIR dnsmasq
COPY build.sh $SRC/
-COPY fuzz_util.cpp $SRC/fuzz_util.cpp
+COPY fuzz*.c $SRC/
+COPY fuzz*.h $SRC/
+
+COPY fuzz_patch.patch $SRC/
diff --git a/projects/dnsmasq/build.sh b/projects/dnsmasq/build.sh
index 049a6488..8fc7b21d 100755
--- a/projects/dnsmasq/build.sh
+++ b/projects/dnsmasq/build.sh
@@ -15,15 +15,34 @@
#
################################################################################
-export OSS_CFLAGS=$CFLAGS
+export ASAN_OPTIONS="detect_leaks=0"
+
+git apply --ignore-space-change --ignore-whitespace $SRC/fuzz_patch.patch
+
+export OSS_CFLAGS="$CFLAGS -g"
sed -i 's/CFLAGS =/CFLAGS = ${OSS_CFLAGS} /g' ./Makefile
sed -i 's/LDFLAGS =/LDFLAGS = ${OSS_CFLAGS} /g' ./Makefile
+
+# Do some modificatiosn to the source
+sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/dhcp-common.c
+sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/netlink.c
+sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/dhcp.c
+sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/network.c
+
+sed -i 's/if (errno != 0/if (errno == 123123/g' ./src/netlink.c
+
+echo "" >> ./src/dnsmasq.c
+echo "ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) {return -1;}" >> ./src/dnsmasq.c
+echo "int fuzz_ioctl(int fd, unsigned long request, void *arg) {return -1;}" >> ./src/dnsmasq.c
make
# Remove main function and create an archive
cd ./src
sed -i 's/int main (/int main2 (/g' ./dnsmasq.c
+sed -i 's/fuzz_recvmsg(/fuzz_recvmsg2(/g' ./dnsmasq.c
+sed -i 's/fuzz_ioctl(/fuzz_ioctl2(/g' ./dnsmasq.c
+
rm dnsmasq.o
$CC $CFLAGS -c dnsmasq.c -o dnsmasq.o -I./ -DVERSION=\'\"UNKNOWN\"\'
ar cr libdnsmasq.a *.o
@@ -31,8 +50,8 @@ ar cr libdnsmasq.a *.o
sed -i 's/class/class2/g' ./dnsmasq.h
sed -i 's/new/new2/g' ./dnsmasq.h
-# Now build fuzzer
-for fuzz_name in util; do
- $CXX $CXXFLAGS -c ${SRC}/fuzz_${fuzz_name}.cpp -o ./fuzz_${fuzz_name}.o -I./ -DVERSION=\'\"UNKNOWN\"\'
- $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./fuzz_${fuzz_name}.o libdnsmasq.a -o $OUT/fuzz_${fuzz_name}
+# Build the fuzzers
+for fuzz_name in dhcp6 rfc1035 auth dhcp util; do
+ $CC $CFLAGS -c $SRC/fuzz_${fuzz_name}.c -I./ -I$SRC/ -DVERSION=\'\"UNKNOWN\"\' -g
+ $CC $CFLAGS $LIB_FUZZING_ENGINE ./fuzz_${fuzz_name}.o libdnsmasq.a -o $OUT/fuzz_${fuzz_name}
done
diff --git a/projects/dnsmasq/fuzz_auth.c b/projects/dnsmasq/fuzz_auth.c
new file mode 100644
index 00000000..4a233e13
--- /dev/null
+++ b/projects/dnsmasq/fuzz_auth.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/*
+ * Targets answer_auth
+ */
+void FuzzAuth(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ int i1 = get_int(&data, &size);
+ int i2 = get_int(&data, &size);
+ int i3 = get_int(&data, &size);
+
+ if (size > (sizeof(struct dns_header) +50)) {
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ time_t now;
+ union mysockaddr peer_addr;
+ answer_auth((struct dns_header *)new_data, new_data + size, size, now, &peer_addr, i1, i2, i3);
+ }
+}
+
+/*
+ * Fuzzer entrypoint.
+ */
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ daemon = NULL;
+ if (size < 1) {
+ return 0;
+ }
+
+ // Initialize mini garbage collector
+ gb_init();
+
+ // Get a value we can use to decide which target to hit.
+ int i = (int)data[0];
+ data += 1;
+ size -= 1;
+
+ int succ = init_daemon(&data, &size);
+
+ if (succ == 0) {
+ cache_init();
+ blockdata_init();
+
+ FuzzAuth(&data, &size);
+
+ cache_start_insert();
+ fuzz_blockdata_cleanup();
+ }
+
+ // Free data in mini garbage collector.
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp.c b/projects/dnsmasq/fuzz_dhcp.c
new file mode 100644
index 00000000..4ba61ca3
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp.c
@@ -0,0 +1,87 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/*
+ * Targets answer_auth
+ */
+void FuzzDhcp(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+ time_t now;
+ int pxe_fd = 0;
+
+ struct iovec *dhpa = malloc(sizeof(struct iovec));
+ if (dhpa == NULL) return;
+
+ char *content = malloc(300);
+ if (content == NULL) {
+ free(dhpa);
+ return;
+ }
+
+ dhpa->iov_base = content;
+ dhpa->iov_len = 300;
+
+ daemon->dhcp_packet = *dhpa;
+
+ syscall_data = data;
+ syscall_size = size;
+
+ dhcp_packet(now, pxe_fd);
+
+ // dnsmasq may change the iov_base if the buffer needs expansion.
+ // Do not free in that case, only free if the buffer stays that same.
+ if (daemon->dhcp_packet.iov_base == content) {
+ free(content);
+ }
+ else{
+ free(daemon->dhcp_packet.iov_base);
+ }
+
+ free(dhpa);
+}
+
+/*
+ * Fuzzer entrypoint.
+ */
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ daemon = NULL;
+ if (size < 1) {
+ return 0;
+ }
+
+ // Initialize mini garbage collector
+ gb_init();
+
+ // Get a value we can use to decide which target to hit.
+ int i = (int)data[0];
+ data += 1;
+ size -= 1;
+
+ int succ = init_daemon(&data, &size);
+
+ if (succ == 0) {
+ cache_init();
+ blockdata_init();
+
+ FuzzDhcp(&data, &size);
+
+ cache_start_insert();
+ fuzz_blockdata_cleanup();
+ }
+
+ // Free data in mini garbage collector.
+ gb_cleanup();
+ return 0;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp6.c b/projects/dnsmasq/fuzz_dhcp6.c
new file mode 100644
index 00000000..fd7a8583
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp6.c
@@ -0,0 +1,83 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/*
+ * Targets answer_auth
+ */
+ static int val213 = 0;
+void FuzzDhcp(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+
+ time_t now;
+ int pxe_fd = 0;
+
+ struct iovec *dhpa = malloc(sizeof(struct iovec));
+ if (dhpa == NULL) return;
+
+ char *content = malloc(300);
+ if (content == NULL) {
+ free(dhpa);
+ return;
+ }
+
+ dhpa->iov_base = content;
+ dhpa->iov_len = 300;
+
+ daemon->dhcp_packet = *dhpa;
+
+ syscall_data = data;
+ syscall_size = size;
+
+ dhcp6_packet(now);
+
+ free(dhpa);
+ free(content);
+}
+
+/*
+ * Fuzzer entrypoint.
+ */
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ daemon = NULL;
+ if (size < 1) {
+ return 0;
+ }
+
+ // Initialize mini garbage collector
+ gb_init();
+
+ // Get a value we can use to decide which target to hit.
+ int i = (int)data[0];
+ data += 1;
+ size -= 1;
+
+ int succ = init_daemon(&data, &size);
+
+ if (succ == 0) {
+ cache_init();
+ blockdata_init();
+
+ FuzzDhcp(&data, &size);
+
+ cache_start_insert();
+ fuzz_blockdata_cleanup();
+ }
+
+ // Free data in mini garbage collector.
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/dnsmasq/fuzz_header.h b/projects/dnsmasq/fuzz_header.h
new file mode 100644
index 00000000..748e709f
--- /dev/null
+++ b/projects/dnsmasq/fuzz_header.h
@@ -0,0 +1,579 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "dnsmasq.h"
+
+extern void fuzz_blockdata_cleanup();
+
+// Simple garbage collector
+#define GB_SIZE 100
+
+void *pointer_arr[GB_SIZE];
+static int pointer_idx = 0;
+
+// If the garbage collector is used then this must be called as first thing
+// during a fuzz run.
+void gb_init() {
+ pointer_idx = 0;
+
+ for (int i = 0; i < GB_SIZE; i++) {
+ pointer_arr[i] = NULL;
+ }
+}
+
+void gb_cleanup() {
+ for(int i = 0; i < GB_SIZE; i++) {
+ if (pointer_arr[i] != NULL) {
+ free(pointer_arr[i]);
+ }
+ }
+}
+
+char *get_null_terminated(const uint8_t **data, size_t *size) {
+#define STR_SIZE 75
+ if (*size < STR_SIZE || (int)*size < 0) {
+ return NULL;
+ }
+
+ char *new_s = malloc(STR_SIZE + 1);
+ memcpy(new_s, *data, STR_SIZE);
+ new_s[STR_SIZE] = '\0';
+
+ *data = *data+STR_SIZE;
+ *size -= STR_SIZE;
+ return new_s;
+}
+
+char *gb_get_random_data(const uint8_t **data, size_t *size, size_t to_get) {
+ if (*size < to_get || (int)*size < 0) {
+ return NULL;
+ }
+
+ char *new_s = malloc(to_get);
+ memcpy(new_s, *data, to_get);
+
+ pointer_arr[pointer_idx++] = (void*)new_s;
+
+ *data = *data + to_get;
+ *size -= to_get;
+
+ return new_s;
+}
+
+char *gb_get_null_terminated(const uint8_t **data, size_t *size) {
+
+ char *nstr = get_null_terminated(data, size);
+ if (nstr == NULL) {
+ return NULL;
+ }
+ pointer_arr[pointer_idx++] = (void*)nstr;
+ return nstr;
+}
+
+char *gb_alloc_data(size_t len) {
+ char *ptr = calloc(1, len);
+ pointer_arr[pointer_idx++] = (void*)ptr;
+
+ return ptr;
+}
+
+short get_short(const uint8_t **data, size_t *size) {
+ if (*size <= 0) return 0;
+ short c = (short)(*data)[0];
+ *data += 1;
+ *size-=1;
+ return c;
+}
+
+int get_int(const uint8_t **data, size_t *size) {
+ if (*size <= 4) return 0;
+ const uint8_t *ptr = *data;
+ int val = *((int*)ptr);
+ *data += 4;
+ *size -= 4;
+ return val;
+}
+// end simple garbage collector.
+
+const uint8_t *syscall_data = NULL;
+size_t syscall_size = 0;
+
+
+int fuzz_ioctl(int fd, unsigned long request, void *arg) {
+ int fd2 = fd;
+ unsigned long request2 = request;
+ void *arg_ptr = arg;
+
+ // SIOCGSTAMP
+ if (request == SIOCGSTAMP) {
+ struct timeval *tv = (struct timeval*)arg_ptr;
+ if (tv == NULL) {
+ return 0;
+ }
+
+ char *rand_tv = gb_get_random_data(&syscall_data, &syscall_size, sizeof(struct timeval));
+ if (rand_tv == NULL) {
+ return -1;
+ }
+
+ memcpy(tv, rand_tv, sizeof(struct timeval));
+ return 0;
+ }
+
+ if (request == SIOCGIFNAME) {
+ //printf("We got a SIOCGIFNAME\n");
+ struct ifreq *ifr = (struct ifreq*)arg_ptr;
+ if (ifr == NULL) {
+ return -1;
+ }
+ for (int i = 0; i < IF_NAMESIZE; i++) {
+ if (syscall_size > 0 && syscall_data != NULL) {
+ ifr->ifr_name[i] = (char)*syscall_data;
+ syscall_data += 1;
+ syscall_size -= 1;
+ }
+ else {
+ ifr->ifr_name[i] = 'A';
+ }
+ }
+ ifr->ifr_name[IF_NAMESIZE-1] = '\0';
+ return 0;
+ //return -1;
+ }
+ if (request == SIOCGIFFLAGS) {
+ return 0;
+ }
+ if (request == SIOCGIFADDR) {
+ return 0;
+ }
+
+ //
+ int retval = ioctl(fd2, request2, arg_ptr);
+ return retval;
+}
+
+
+// Sysytem call wrappers
+static char v = 0;
+ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) {
+
+ struct iovec *target = msg->msg_iov;
+
+ //printf("recvmsg 1 \n");
+ if (syscall_size > 1) {
+ char r = *syscall_data;
+ syscall_data += 1;
+ syscall_size -= 1;
+
+ if (r == 12) {
+ //printf("recvmsg 2\n");
+ return -1;
+ }
+ }
+
+ int j = 0;
+ if (msg->msg_control != NULL) {
+ for (;j < CMSG_SPACE(sizeof(struct in_pktinfo)); j++)
+ {
+ if (syscall_size > 0 && syscall_data != NULL) {
+ ((char*)msg->msg_control)[j] = *syscall_data;
+ syscall_data += 1;
+ syscall_size -= 1;
+ }
+ else {
+ ((char*)msg->msg_control)[j] = 'A';
+ }
+ }
+ }
+
+ int i = 0;
+ for (; i < target->iov_len; i++) {
+ if (syscall_size > 0 && syscall_data != NULL) {
+ ((char*)target->iov_base)[i] = *syscall_data;
+ syscall_data += 1;
+ syscall_size -= 1;
+ }
+ else {
+ ((char*)target->iov_base)[i] = 'A';
+ }
+ }
+
+ if (msg->msg_namelen > 0) {
+ memset(msg->msg_name, 0, msg->msg_namelen);
+ }
+
+ return i;
+}
+
+
+// dnsmasq specific stuff
+int init_daemon(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ int retval = 0;
+
+#define CLEAN_IF_NULL(arg) if (arg == NULL) goto cleanup;
+
+ // Initialize daemon
+ daemon = (struct daemon*)gb_alloc_data(sizeof(struct daemon));
+ CLEAN_IF_NULL(daemon)
+
+ // daemon misc
+ daemon->max_ttl = get_int(&data, &size);
+ daemon->neg_ttl = get_int(&data, &size);
+ daemon->local_ttl = get_int(&data, &size);
+ daemon->min_cache_ttl = get_int(&data, &size);
+
+ // daemon->namebuff.
+ char *daemon_namebuff = gb_get_null_terminated(&data, &size);
+ daemon->namebuff = daemon_namebuff;
+
+ // daemon->naptr
+ struct naptr *naptr_ptr = (struct naptr*)gb_alloc_data(sizeof(struct naptr));
+ char *naptr_name = gb_get_null_terminated(&data, &size);
+ char *naptr_replace = gb_get_null_terminated(&data, &size);
+ char *naptr_regexp = gb_get_null_terminated(&data, &size);
+ char *naptr_services = gb_get_null_terminated(&data, &size);
+ char *naptr_flags = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(naptr_ptr)
+ CLEAN_IF_NULL(naptr_name)
+ CLEAN_IF_NULL(naptr_replace)
+ CLEAN_IF_NULL(naptr_regexp)
+ CLEAN_IF_NULL(naptr_services)
+ CLEAN_IF_NULL(naptr_flags)
+
+ naptr_ptr->name = naptr_name;
+ naptr_ptr->replace = naptr_replace;
+ naptr_ptr->regexp = naptr_regexp;
+ naptr_ptr->services = naptr_services;
+ naptr_ptr->flags = naptr_flags;
+
+ daemon->naptr = naptr_ptr;
+
+ // daemon->int_names
+ struct interface_name *int_namses = (struct interface_name*)gb_alloc_data(sizeof(struct interface_name));
+
+ char *int_name = gb_get_null_terminated(&data, &size);
+ char *int_intr = gb_get_null_terminated(&data, &size);
+ CLEAN_IF_NULL(int_namses)
+ CLEAN_IF_NULL(int_name)
+ CLEAN_IF_NULL(int_intr)
+ int_namses->name = int_name;
+ int_namses->intr = int_intr;
+
+ struct addrlist *d_addrlist = (struct addrlist*)gb_alloc_data(sizeof(struct addrlist));
+ CLEAN_IF_NULL(d_addrlist)
+ d_addrlist->flags = get_int(&data, &size);
+ d_addrlist->prefixlen = get_int(&data, &size);
+ int_namses->addr = d_addrlist;
+
+ daemon->int_names = int_namses;
+
+ if (size > *size2) {
+ goto cleanup;
+ }
+
+ // daemon->addrbuf
+ char *adbuf = gb_alloc_data(200);
+ CLEAN_IF_NULL(adbuf)
+ daemon->addrbuff = adbuf;
+
+ // daemon->auth_zones
+ struct auth_zone *d_az = (struct auth_zone*)gb_alloc_data(sizeof(struct auth_zone));
+ char *auth_domain = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(d_az)
+ CLEAN_IF_NULL(auth_domain)
+ d_az->domain = auth_domain;
+ daemon->auth_zones = d_az;
+
+ // deamon->mxnames
+ struct mx_srv_record *mx_srv_rec = (struct mx_srv_record*)gb_alloc_data(sizeof(struct mx_srv_record));
+ char *mx_name = gb_get_null_terminated(&data, &size);
+ char *mx_target = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(mx_srv_rec)
+ CLEAN_IF_NULL(mx_target)
+ CLEAN_IF_NULL(mx_name)
+
+ mx_srv_rec->next = daemon->mxnames;
+ daemon->mxnames = mx_srv_rec;
+ mx_srv_rec->name = mx_name;
+ mx_srv_rec->target = mx_target;
+ mx_srv_rec->issrv = get_int(&data, &size);
+ mx_srv_rec->weight = get_int(&data, &size);
+ mx_srv_rec->priority = get_int(&data, &size);
+ mx_srv_rec->srvport = get_int(&data, &size);
+ //data += 40;
+ //size -= 40;
+
+ if (size > *size2) {
+ goto cleanup;
+ }
+
+ // daemon->txt
+ struct txt_record *txt_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record));
+ char *txt_record_name = gb_get_null_terminated(&data, &size);
+ char *txt_record_txt = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(txt_record)
+ CLEAN_IF_NULL(txt_record_name)
+ CLEAN_IF_NULL(txt_record_txt)
+
+ txt_record->name = txt_record_name;
+ txt_record->txt = (unsigned char*)txt_record_txt;
+ txt_record->class2 = (get_short(&data, &size) % 10);
+ daemon->txt = txt_record;
+
+ // daemon->rr
+ struct txt_record *rr_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record));
+ char *rr_record_name = gb_get_null_terminated(&data, &size);
+ char *rr_record_txt = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(rr_record)
+ CLEAN_IF_NULL(rr_record_name)
+ CLEAN_IF_NULL(rr_record_txt)
+
+ rr_record->name = rr_record_name;
+ rr_record->txt = (unsigned char*)rr_record_txt;
+ rr_record->class2 = (get_short(&data, &size) % 10);
+ daemon->rr = rr_record;
+
+ if (size > *size2) {
+ goto cleanup;
+ }
+
+ // daemon->relay4
+ //struct dhcp_relay *dr = (struct dhcp_relay*)gb_alloc_data(sizeof(struct dhcp_relay));
+ struct dhcp_relay *dr = (struct dhcp_relay*)gb_get_random_data(&data, &size, sizeof(struct dhcp_relay));
+ char *dr_interface = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(dr)
+ CLEAN_IF_NULL(dr_interface)
+ dr->interface = dr_interface;
+ dr->next = NULL;
+ dr->current = NULL;
+ daemon->relay4 = dr;
+
+ // deamon->bridges
+ struct dhcp_bridge *db = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge));
+ char *db_interface = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(db)
+ CLEAN_IF_NULL(db_interface)
+
+ if (strlen(db_interface) > IF_NAMESIZE) {
+ for (int i = 0; i < IF_NAMESIZE; i++) {
+ db->iface[i] = db_interface[i];
+ }
+ } else {
+ for (int i = 0; i < strlen(db_interface); i++) {
+ db->iface[i] = db_interface[i];
+ }
+ }
+
+
+ struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge));
+ //struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_get_random_data(&data, &size, sizeof(struct dhcp_bridge));
+ char *db_alias_interface = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(db_alias)
+ CLEAN_IF_NULL(db_alias_interface)
+
+ if (strlen(db_alias_interface) > IF_NAMESIZE) {
+ for (int i = 0; i < IF_NAMESIZE; i++) {
+ db_alias->iface[i] = db_alias_interface[i];
+ }
+ } else {
+ for (int i = 0; i < strlen(db_alias_interface); i++) {
+ db_alias->iface[i] = db_alias_interface[i];
+ }
+ }
+ db->alias = db_alias;
+ daemon->bridges = db;
+
+ // daemon->if_names
+ struct iname *in = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+ char *iname_name = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(in)
+ CLEAN_IF_NULL(iname_name)
+
+ in->name = iname_name;
+ in->next = NULL;
+
+ daemon->if_names = in;
+
+ // daemon->if_addrs
+ struct iname *in_addr = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+ char *iname_name_addr = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(in_addr)
+ CLEAN_IF_NULL(iname_name_addr)
+
+ in_addr->name = iname_name_addr;
+ in_addr->next = NULL;
+
+ daemon->if_addrs = in_addr;
+
+ // daemon->if_except
+ struct iname *in_except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+ char *iname_name_except = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(in_except)
+ CLEAN_IF_NULL(iname_name_except)
+
+ in_except->name = iname_name_except;
+ in_except->next = NULL;
+
+ daemon->if_except = in_except;
+
+ // daemon->dhcp_except
+ struct iname *except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+ char *name_except = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(except)
+ CLEAN_IF_NULL(name_except)
+
+ except->name = name_except;
+ except->next = NULL;
+
+ daemon->dhcp_except = except;
+
+ // daemon->authinterface
+ struct iname *auth_interface = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname));
+ char *auth_name = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(auth_interface)
+ CLEAN_IF_NULL(auth_name)
+
+ auth_interface->name = auth_name;
+ auth_interface->next = NULL;
+
+ daemon->authinterface = auth_interface;
+
+
+ // daemon->cnames
+ struct cname *cn = (struct cname*)gb_alloc_data(sizeof(struct cname));
+ char *cname_alias = gb_get_null_terminated(&data, &size);
+ char *cname_target = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(cn)
+ CLEAN_IF_NULL(cname_alias)
+ CLEAN_IF_NULL(cname_target)
+
+ cn->alias = cname_alias;
+ cn->target = cname_target;
+ daemon->cnames = cn;
+
+
+ // daemon->ptr
+ struct ptr_record *ptr = (struct ptr_record *)gb_alloc_data(sizeof(struct ptr_record));
+ CLEAN_IF_NULL(ptr)
+
+ char *ptr_name = gb_get_null_terminated(&data, &size);
+ CLEAN_IF_NULL(ptr_name)
+ ptr->name = ptr_name;
+ daemon->ptr = ptr;
+
+ if (size > *size2) {
+ goto cleanup;
+ }
+
+ // daemon->dhcp
+ struct dhcp_context *dhcp_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context));
+
+ char *dhcp_c_temp_in = gb_get_null_terminated(&data, &size);
+
+ struct dhcp_netid *dhcp_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid));
+ char *dhcp_netid_net = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(dhcp_c)
+ CLEAN_IF_NULL(dhcp_c_temp_in)
+ CLEAN_IF_NULL(dhcp_c_netid)
+ CLEAN_IF_NULL(dhcp_netid_net)
+
+ dhcp_c->next = NULL;
+ dhcp_c->current = NULL;
+ dhcp_c_netid->net = dhcp_netid_net;
+ dhcp_c->filter = dhcp_c_netid;
+ dhcp_c->template_interface = dhcp_c_temp_in;
+
+ daemon->dhcp = dhcp_c;
+
+
+ // daemon->dhcp6
+ struct dhcp_context *dhcp6_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context));
+
+ char *dhcp6_c_temp_in = gb_get_null_terminated(&data, &size);
+
+ struct dhcp_netid *dhcp6_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid));
+ char *dhcp6_netid_net = gb_get_null_terminated(&data, &size);
+
+ CLEAN_IF_NULL(dhcp6_c)
+ CLEAN_IF_NULL(dhcp6_c_temp_in)
+ CLEAN_IF_NULL(dhcp6_c_netid)
+ CLEAN_IF_NULL(dhcp6_netid_net)
+
+ dhcp6_c->next = NULL;
+ dhcp6_c->current = NULL;
+ dhcp6_c_netid->net = dhcp6_netid_net;
+ dhcp6_c->filter = dhcp6_c_netid;
+ dhcp6_c->template_interface = dhcp6_c_temp_in;
+
+ daemon->dhcp6 = dhcp6_c;
+
+ // daemon->doing_dhcp6
+ daemon->doing_dhcp6 = 1;
+
+ // daemon->dhcp_buffs
+ char *dhcp_buff = gb_alloc_data(DHCP_BUFF_SZ);
+ char *dhcp_buff2 = gb_alloc_data(DHCP_BUFF_SZ);
+ char *dhcp_buff3 = gb_alloc_data(DHCP_BUFF_SZ);
+
+ CLEAN_IF_NULL(dhcp_buff)
+ CLEAN_IF_NULL(dhcp_buff2)
+ CLEAN_IF_NULL(dhcp_buff3)
+
+ daemon->dhcp_buff = dhcp_buff;
+ daemon->dhcp_buff2 = dhcp_buff2;
+ daemon->dhcp_buff3 = dhcp_buff3;
+
+
+
+ // daemon->ignore_addr
+ struct bogus_addr *bb = (struct bogus_addr *)gb_alloc_data(sizeof(struct bogus_addr));
+ CLEAN_IF_NULL(bb)
+
+ daemon->ignore_addr = bb;
+
+ // daemon->doctors
+ if (size > *size2) {
+ goto cleanup;
+ }
+
+ struct doctor *doctors = (struct doctor *)gb_alloc_data(sizeof(struct doctor));
+ CLEAN_IF_NULL(doctors)
+
+ doctors->next = NULL;
+ daemon->doctors = doctors;
+
+ retval = 0;
+ goto ret;
+cleanup:
+ retval = -1;
+
+ret:
+ return retval;
+}
diff --git a/projects/dnsmasq/fuzz_patch.patch b/projects/dnsmasq/fuzz_patch.patch
new file mode 100644
index 00000000..b8d254fb
--- /dev/null
+++ b/projects/dnsmasq/fuzz_patch.patch
@@ -0,0 +1,170 @@
+diff --git a/src/blockdata.c b/src/blockdata.c
+index f7740b5..b02915a 100644
+--- a/src/blockdata.c
++++ b/src/blockdata.c
+@@ -15,16 +15,22 @@
+ */
+
+ #include "dnsmasq.h"
++#include <assert.h>
+
+ static struct blockdata *keyblock_free;
+ static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
+
++void *total_allocated[200] = {0};
++static int fuzz_total_alloc_ptr = 0;
++
+ static void blockdata_expand(int n)
+ {
+ struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
+
+ if (new)
+ {
++ assert(fuzz_total_alloc_ptr < 200);
++ total_allocated[fuzz_total_alloc_ptr++] = (void*)new;
+ int i;
+
+ new[n-1].next = keyblock_free;
+@@ -45,11 +51,23 @@ void blockdata_init(void)
+ blockdata_count = 0;
+ blockdata_hwm = 0;
+
++ fuzz_total_alloc_ptr = 0;
++ for (int m = 0; m < 200; m++)
++ total_allocated[m] = NULL;
++
+ /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
+ if (option_bool(OPT_DNSSEC_VALID))
+ blockdata_expand(daemon->cachesize);
+ }
+
++void fuzz_blockdata_cleanup() {
++ for (int i = 0; i < 200; i++) {
++ if (total_allocated[i] != NULL) {
++ free(total_allocated[i]);
++ }
++ }
++}
++
+ void blockdata_report(void)
+ {
+ my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
+diff --git a/src/dhcp.c b/src/dhcp.c
+index 97324f2..1751df7 100644
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -183,18 +183,26 @@ void dhcp_packet(time_t now, int pxe_fd)
+ recvtime = tv.tv_sec;
+
+ if (msg.msg_controllen >= sizeof(struct cmsghdr))
+- for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+- if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
+- {
+- union {
+- unsigned char *c;
+- struct in_pktinfo *p;
+- } p;
+- p.c = CMSG_DATA(cmptr);
+- iface_index = p.p->ipi_ifindex;
+- if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
+- unicast_dest = 1;
+- }
++ {
++ int tmp_val = 0;
++ for (cmptr = CMSG_FIRSTHDR(&msg);
++ cmptr && tmp_val < 1;
++ tmp_val++) {
++ //cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++ tmp_val++;
++ if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
++ {
++ union {
++ unsigned char *c;
++ struct in_pktinfo *p;
++ } p;
++ p.c = CMSG_DATA(cmptr);
++ iface_index = p.p->ipi_ifindex;
++ if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
++ unicast_dest = 1;
++ }
++ }
++ }
+
+ #elif defined(HAVE_BSD_NETWORK)
+ if (msg.msg_controllen >= sizeof(struct cmsghdr))
+diff --git a/src/dhcp6.c b/src/dhcp6.c
+index 2be877f..d3f5739 100644
+--- a/src/dhcp6.c
++++ b/src/dhcp6.c
+@@ -116,10 +116,14 @@ void dhcp6_packet(time_t now)
+ msg.msg_iov = &daemon->dhcp_packet;
+ msg.msg_iovlen = 1;
+
+- if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
++ if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1){
+ return;
+-
+- for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
++ }
++
++ int tmp_val = 0;
++// for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr && tmp_val < 1; tmp_val++) {
++ tmp_val++;
+ if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
+ {
+ union {
+@@ -131,9 +135,11 @@ void dhcp6_packet(time_t now)
+ if_index = p.p->ipi6_ifindex;
+ dst_addr = p.p->ipi6_addr;
+ }
++ }
+
+- if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
++ if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) {
+ return;
++ }
+
+ if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
+ {
+diff --git a/src/netlink.c b/src/netlink.c
+index 7840ef9..2419897 100644
+--- a/src/netlink.c
++++ b/src/netlink.c
+@@ -197,8 +197,13 @@ int iface_enumerate(int family, void *parm, int (*callback)())
+ if (errno != 0)
+ return 0;
+
++ int valval = 0;
+ while (1)
+ {
++ valval++;
++ if (valval > 300) {
++ return -1;
++ }
+ if ((len = netlink_recv(0)) == -1)
+ {
+ if (errno == ENOBUFS)
+diff --git a/src/network.c b/src/network.c
+index 3ef71b9..e305c03 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -697,6 +697,7 @@ int enumerate_interfaces(int reset)
+ struct auth_zone *zone;
+ #endif
+ struct server *serv;
++ int iteration = 0;
+
+ /* Do this max once per select cycle - also inhibits netlink socket use
+ in TCP child processes. */
+@@ -734,6 +735,10 @@ int enumerate_interfaces(int reset)
+ }
+
+ again:
++ if (iteration > 100) {
++ return 0;
++ }
++ iteration += 1;
+ /* Mark interfaces for garbage collection */
+ for (iface = daemon->interfaces; iface; iface = iface->next)
+ iface->found = 0;
diff --git a/projects/dnsmasq/fuzz_rfc1035.c b/projects/dnsmasq/fuzz_rfc1035.c
new file mode 100644
index 00000000..f0f75c59
--- /dev/null
+++ b/projects/dnsmasq/fuzz_rfc1035.c
@@ -0,0 +1,271 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+/*
+ * Targets "extract_addresses"
+ */
+void FuzzExtractTheAddress(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ char *new_name = NULL;
+ new_name = get_null_terminated(&data, &size);
+ pointer_arr[pointer_idx++] = (void*)new_name;
+
+ int check_rebind = get_int(&data, &size);
+ int is_sign = get_int(&data, &size);
+ int secure = get_int(&data, &size);
+
+ if (size > (sizeof(struct dns_header) +50)) {
+ char *new_data = malloc(size);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ time_t now;
+ int doctored = 0;
+ extract_addresses((struct dns_header *)new_data, size, new_name, now, NULL, check_rebind, is_sign, 0, secure, &doctored);
+ }
+}
+
+
+/*
+ * Targets "answer_request"
+ */
+void FuzzAnswerTheRequest(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ struct in_addr local_addr;
+ struct in_addr local_netmask;
+ time_t now;
+
+ int i1 = get_int(&data, &size);
+ int i2 = get_int(&data, &size);
+ int i3 = get_int(&data, &size);
+
+ if (size > (sizeof(struct dns_header) +50)) {
+ char *new_data = malloc(size);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ answer_request((struct dns_header *)new_data, new_data+size, size, local_addr, local_netmask, now, i1, i2, i3);
+ }
+
+}
+
+/*
+ * Targets "check_for_ignored_address"
+ */
+void FuzzIgnoredAddress(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ if (size > (sizeof(struct dns_header) +50)) {
+ //return 0;
+ char *new_data = malloc(size);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ check_for_ignored_address((struct dns_header *)new_data, size);
+ }
+}
+
+/*
+ * Targets "check_for_local_domain"
+ */
+void FuzzCheckLocalDomain(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ time_t now;
+ check_for_local_domain(new_data, now);
+}
+
+/*
+ * Targets "extract_request"
+ */
+void FuzzExtractRequest(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ char *new_name = NULL;
+ new_name = get_null_terminated(&data, &size);
+
+ if (new_name == NULL) {
+ return ;
+ }
+ pointer_arr[pointer_idx++] = (void*)new_name;
+
+ if (size > (sizeof(struct dns_header) +50)) {
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ unsigned short typeb;
+ extract_request((struct dns_header *)new_data, size, new_name, &typeb);
+ }
+}
+
+
+/*
+ * Targets "in_arpa_name_2_addr"
+ */
+void FuzzArpaName2Addr(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ char *new_name = NULL;
+ new_name = get_null_terminated(&data, &size);
+
+ if (new_name == NULL) {
+ return ;
+ }
+ pointer_arr[pointer_idx++] = (void*)new_name;
+ union all_addr addr;
+ in_arpa_name_2_addr(new_name, &addr);
+ return;
+}
+
+void FuzzResizePacket(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ char *new_packet = malloc(50);
+
+ if (size > (sizeof(struct dns_header) + 50)) {
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ resize_packet((struct dns_header *)new_data, size, (unsigned char*)new_packet, 50);
+ }
+ free(new_packet);
+}
+
+void FuzzSetupReply(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ if (size > (sizeof(struct dns_header) + 50)) {
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ setup_reply((struct dns_header *)new_data, 0, 0);
+ }
+}
+
+
+void FuzzCheckForBogusWildcard(const uint8_t **data2, size_t *size2) {
+ const uint8_t *data = *data2;
+ size_t size = *size2;
+
+ char *nname = gb_get_null_terminated(&data, &size);
+ if (nname == NULL) {
+ return;
+ }
+
+
+ if (size > (sizeof(struct dns_header) + 50)) {
+ char *new_data = malloc(size+1);
+ memset(new_data, 0, size);
+ memcpy(new_data, data, size);
+ new_data[size] = '\0';
+ pointer_arr[pointer_idx++] = (void*)new_data;
+
+ time_t now;
+ check_for_bogus_wildcard((struct dns_header *)new_data, size, nname, now);
+ }
+}
+
+
+/*
+ * Fuzzer entrypoint.
+ */
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ daemon = NULL;
+ //printf("Running fuzzer\n");
+ if (size < 1) {
+ return 0;
+ }
+
+ // Initialize mini garbage collector
+ gb_init();
+
+ // Get a value we can use to decide which target to hit.
+ int i = (int)data[0];
+ data += 1;
+ size -= 1;
+
+ int succ = init_daemon(&data, &size);
+
+ if (succ == 0) {
+ cache_init();
+ blockdata_init();
+
+ //i = 7;
+#define TS 9
+ if ((i % TS) == 0) {
+ FuzzExtractTheAddress(&data,&size);
+ }
+ else if ((i % TS) == 1) {
+ FuzzAnswerTheRequest(&data,&size);
+ }
+ else if ((i % TS) == 2) {
+ FuzzCheckLocalDomain(&data, &size);
+ }
+ else if ((i % TS) == 3) {
+ FuzzExtractRequest(&data, &size);
+ }
+ else if ((i % TS) == 4) {
+ FuzzArpaName2Addr(&data, &size);
+ }
+ else if ((i %TS) == 5) {
+ FuzzResizePacket(&data, &size);
+ }
+ else if ((i %TS) == 6) {
+ FuzzSetupReply(&data, &size);
+ }
+ else if ((i % TS) == 7) {
+ FuzzCheckForBogusWildcard(&data, &size);
+ }
+ else {
+ FuzzIgnoredAddress(&data, &size);
+ }
+ cache_start_insert();
+ fuzz_blockdata_cleanup();
+ }
+
+ // Free data in mini garbage collector.
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/dnsmasq/fuzz_util.c b/projects/dnsmasq/fuzz_util.c
new file mode 100644
index 00000000..7ab723cc
--- /dev/null
+++ b/projects/dnsmasq/fuzz_util.c
@@ -0,0 +1,66 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ // init fuzz garbage collector
+ gb_init();
+
+ int succ = init_daemon(&data, &size);
+ if (succ == 0) {
+ char *t1 = gb_get_null_terminated(&data, &size);
+ char *t2 = gb_get_null_terminated(&data, &size);
+ if (t1 != NULL && t2 != NULL) {
+
+ // Util logic
+ hostname_isequal(t1, t2);
+
+ legal_hostname(t1);
+ char *tmp = canonicalise(t2, NULL);
+ if (tmp != NULL) {
+ free(tmp);
+ }
+
+ char *tmp_out = (char *)malloc(30);
+ int mac_type;
+ parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, NULL);
+ parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, &mac_type);
+ free(tmp_out);
+
+ wildcard_match(t1, t2);
+ if (strlen(t1) < strlen(t2)) {
+ wildcard_matchn(t1, t2, strlen(t1));
+ } else {
+ wildcard_matchn(t1, t2, strlen(t2));
+ }
+ hostname_issubdomain(t1, t2);
+
+ union all_addr addr1;
+ memset(&addr1, 0, sizeof(union all_addr));
+ is_name_synthetic(0, t1, &addr1);
+
+ if (size > sizeof(struct dns_header)) {
+ hash_questions(data, size, t2);
+
+ rrfilter(data, size, 0);
+ }
+ }
+
+ fuzz_blockdata_cleanup();
+ }
+
+ // cleanup
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/dnsmasq/fuzz_util.cpp b/projects/dnsmasq/fuzz_util.cpp
deleted file mode 100644
index fa739de6..00000000
--- a/projects/dnsmasq/fuzz_util.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright 2021 Google LLC
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-extern "C" {
-#include "dnsmasq.h"
-}
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- FuzzedDataProvider provider(data, size);
-
- std::string inp1 = provider.ConsumeRandomLengthString();
- std::string inp2 = provider.ConsumeRandomLengthString();
-
- // Util logic
- hostname_isequal(inp1.c_str(), inp2.c_str());
-
- legal_hostname((char *)inp1.c_str());
- char *tmp = canonicalise((char *)inp1.c_str(), NULL);
- if (tmp != NULL) {
- free(tmp);
- }
-
- char *tmp_out = (char *)malloc(30);
- int mac_type;
- parse_hex((char *)inp1.c_str(), (unsigned char *)tmp_out, 30, NULL, NULL);
- parse_hex((char *)inp1.c_str(), (unsigned char *)tmp_out, 30, NULL,
- &mac_type);
- free(tmp_out);
-
- wildcard_match((char *)inp1.c_str(), (char *)inp2.c_str());
- if (inp1.size() < inp2.size()) {
- wildcard_matchn(inp1.c_str(), inp2.c_str(), inp1.size());
- } else {
- wildcard_matchn(inp1.c_str(), inp2.c_str(), inp2.size());
- }
- hostname_issubdomain((char *)inp1.c_str(), (char *)inp2.c_str());
-
- // rfc1035-related logic
- size_t plen = sizeof(struct dns_header) + size;
- char *tmp_dns_packet = (char *)malloc(plen);
- char *tmp3 = tmp_dns_packet + sizeof(struct dns_header);
- memcpy(tmp3, data, size);
-
- extract_name((struct dns_header *)tmp_dns_packet, plen,
- (unsigned char **)&tmp3, (char *)inp1.c_str(), 0, 0);
- free(tmp_dns_packet);
-
- union all_addr addr;
- in_arpa_name_2_addr((char *)inp1.c_str(), &addr);
-
- return 0;
-}