]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
[Fuzzing] updates for oss-fuzz Ideal integration 584/head
authorArjun Singh <ajsinghyadav00@gmail.com>
Sat, 27 May 2023 15:52:12 +0000 (21:22 +0530)
committerArjun Singh <ajsinghyadav00@gmail.com>
Tue, 30 May 2023 15:45:37 +0000 (21:15 +0530)
Signed-off-by: Arjun Singh <ajsinghyadav00@gmail.com>
23 files changed:
README.md
configure.ac
src/daemon/protocols/edp.c
tests/Makefile.am
tests/decode.c
tests/fuzz_cdp.c [new file with mode: 0644]
tests/fuzz_edp.c [new file with mode: 0644]
tests/fuzz_lldp.c [new file with mode: 0644]
tests/fuzz_sonmp.c [new file with mode: 0644]
tests/fuzzing_seed_corpus/fuzz_cdp_seed_corpus/cdp.0.raw [moved from tests/fuzzer/seed-corpus/cdp.0.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_cdp_seed_corpus/cdp.1.raw [moved from tests/fuzzer/seed-corpus/cdp.1.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_cdp_seed_corpus/cdp.2.raw [moved from tests/fuzzer/seed-corpus/cdp.2.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_cdp_seed_corpus/cdp.3.raw [moved from tests/fuzzer/seed-corpus/cdp.3.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_edp_seed_corpus/edp.0.raw [moved from tests/fuzzer/seed-corpus/edp.0.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_edp_seed_corpus/edp.1.raw [moved from tests/fuzzer/seed-corpus/edp.1.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_edp_seed_corpus/edp.2.raw [moved from tests/fuzzer/seed-corpus/edp.2.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_edp_seed_corpus/edp.3.raw [moved from tests/fuzzer/seed-corpus/edp.3.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_edp_seed_corpus/edp.4.raw [moved from tests/fuzzer/seed-corpus/edp.4.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_lldp_seed_corpus/lldp.0.raw [moved from tests/fuzzer/seed-corpus/lldp.0.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_lldp_seed_corpus/lldp.1.raw [moved from tests/fuzzer/seed-corpus/lldp.1.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_sonmp_seed_corpus/sonmp.0.raw [moved from tests/fuzzer/seed-corpus/sonmp.0.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_sonmp_seed_corpus/sonmp.1.raw [moved from tests/fuzzer/seed-corpus/sonmp.1.raw with 100% similarity]
tests/fuzzing_seed_corpus/fuzz_sonmp_seed_corpus/sonmp.2.raw [moved from tests/fuzzer/seed-corpus/sonmp.2.raw with 100% similarity]

index 8863d3618f164fb09857efa85ec40bdc41e8c832..99fe9966cd75e300413f8970254f4994259b90e3 100644 (file)
--- a/README.md
+++ b/README.md
@@ -358,28 +358,52 @@ To enable code coverage, use:
 
 ## Fuzzing
 
-### With libfuzzer
+### With [libfuzzer](https://llvm.org/docs/LibFuzzer.html)
 
-Build with `--enable-fuzzer` and `--enable-sanitizers`, then run `./fuzz-decode fuzzer/corpus
-fuzzer/seed-corpus` in `tests` folder. For example:
+using address sanitizer:
+```bash
+export CC=clang
+export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link"
+export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
+```
 
-- using address sanitizer: `./configure --enable-fuzzer --enable-sanitizers=address CFLAGS="-O1 -fsanitize-address-use-after-scope" CC=clang`
-- using undefined-behaviour sanitizer: `./configure --enable-fuzzer --enable-sanitizers=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr CFLAGS="-O1 -fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" CC=clang`
-- using memory sanitizer : `./configure --enable-fuzzer --enable-sanitizers=memory CFLAGS="-O1 -fsanitize-memory-track-origins" CC=clang`
+using undefined-behaviour sanitizer:
+```bash
+export CC=clang
+export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -fsanitize=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr -fsanitize=fuzzer-no-link"
+export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
+```
 
-### With AFL
+using memory sanitizer:
+```bash
+export CC=clang
+export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -fsanitize=memory -fsanitize-memory-track-origins -fsanitize=fuzzer-no-link"
+export LIB_FUZZING_ENGINE="-fsanitize=fuzzer"
+```
 
-You can use [afl](http://lcamtuf.coredump.cx/afl/) to test some
-aspects of lldpd. To test frame decoding, you can do something like
-that:
+build and run:
+```
+./configure --disable-shared --enable-pie --enable-fuzzer=$LIB_FUZZING_ENGINE
+make
+cd tests/
+./fuzz_cdp   fuzzing_seed_corpus/fuzz_cdp_seed_corpus
+./fuzz_edp   fuzzing_seed_corpus/fuzz_edp_seed_corpus
+./fuzz_lldp  fuzzing_seed_corpus/fuzz_lldp_seed_corpus
+./fuzz_sonmp fuzzing_seed_corpus/fuzz_sonmp_seed_corpus
+```
 
-    export AFL_USE_ASAN=1 # only on 32bit arch
-    ./configure CC=afl-gcc
-    make clean check
-    cd tests
-    mkdir inputs
-    mv *.pcap inputs
-    afl-fuzz -i inputs -o outputs ./decode @@
+### With [AFL++](https://aflplus.plus)
+
+You can use AFL++ to test some other aspects of lldpd. To test frame decoding:
+```bash
+export CC=afl-clang-fast
+./configure --disable-shared --enable-pie
+make clean check
+cd tests
+mkdir inputs
+mv *.pcap inputs
+afl-fuzz -i inputs -o outputs ./decode @@
+```
 
 ## Embedding
 
index 65e828aa848a99f952de92fc42342d4974287458..5c8807b3a7f370aff2bf6465aa8526e25bb12164 100644 (file)
@@ -159,6 +159,7 @@ case "$enableval" in
 esac
 if test x"$fuzzer" != x; then
   AC_SUBST([FUZZ_DECODE_ENGINE], ["$fuzzer"])
+  AX_CFLAGS_GCC_OPTION([-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION], [LLDP_CFLAGS])
 fi
   ])
 
index 35ae912df056e0f6ad4ea2e1460d2327bdd7bde2..79b6c51044803c7af2790c31558abdaf6d7c585f 100644 (file)
@@ -305,12 +305,14 @@ edp_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardwar
        }
        PEEK_BYTES(chassis->c_id, ETHER_ADDR_LEN);
 
+#  ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
        /* Let's check checksum */
        if (frame_checksum(pos_edp, edp_len, 0) != 0) {
                log_warnx("edp", "incorrect EDP checksum for frame received on %s",
                    hardware->h_ifname);
                goto malformed;
        }
+#  endif
 
        while (length && !gotend) {
                if (length < 4) {
@@ -345,6 +347,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardwar
                        port->p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
                        edp_slot = PEEK_UINT16;
                        edp_port = PEEK_UINT16;
+                       free(port->p_id);
                        if (asprintf(&port->p_id, "%d/%d", edp_slot + 1,
                                edp_port + 1) == -1) {
                                log_warn("edp",
@@ -353,6 +356,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardwar
                                goto malformed;
                        }
                        port->p_id_len = strlen(port->p_id);
+                       free(port->p_descr);
                        if (asprintf(&port->p_descr, "Slot %d / Port %d", edp_slot + 1,
                                edp_port + 1) == -1) {
                                log_warn("edp",
@@ -363,6 +367,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardwar
                        PEEK_DISCARD_UINT16; /* vchassis */
                        PEEK_DISCARD(6);     /* Reserved */
                        PEEK_BYTES(version, 4);
+                       free(chassis->c_descr);
                        if (asprintf(&chassis->c_descr,
                                "EDP enabled device, version %d.%d.%d.%d", version[0],
                                version[1], version[2], version[3]) == -1) {
index c3c0295bddda0a920351cfaf9f22a070e5e2643c..c41f6730fa11ce1f06d32c621df139aae41aca98 100644 (file)
@@ -7,14 +7,6 @@ decode_SOURCES = decode.c \
        $(top_srcdir)/src/daemon/lldpd.h \
        pcap-hdr.h
 
-if ENABLE_FUZZ_DECODE
-noinst_PROGRAMS = fuzz-decode
-fuzz_decode_CFLAGS = $(AM_CFLAGS) -DFUZZ_DECODE
-fuzz_decode_LDADD = $(FUZZ_DECODE_ENGINE) $(LDADD)
-fuzz_decode_SOURCES = decode.c \
-       $(top_srcdir)/src/daemon/lldpd.h
-endif
-
 LDADD = $(top_builddir)/src/daemon/liblldpd.la @libevent_LDFLAGS@
 if ENABLE_SYSTEMTAP
 LDADD += $(top_builddir)/src/daemon/probes.o
@@ -70,4 +62,24 @@ check_PROGRAMS += $(TESTS)
 
 endif
 
+if ENABLE_FUZZ_DECODE
+noinst_PROGRAMS = fuzz_lldp fuzz_cdp fuzz_sonmp fuzz_edp
+
+fuzz_lldp_SOURCES = fuzz_lldp.c \
+       $(top_srcdir)/src/daemon/lldpd.h
+fuzz_lldp_LDADD = $(top_builddir)/src/daemon/liblldpd.la $(LDADD) $(FUZZ_DECODE_ENGINE)
+
+fuzz_cdp_SOURCES = fuzz_cdp.c \
+       $(top_srcdir)/src/daemon/lldpd.h
+fuzz_cdp_LDADD = $(top_builddir)/src/daemon/liblldpd.la $(LDADD) $(FUZZ_DECODE_ENGINE)
+
+fuzz_sonmp_SOURCES = fuzz_sonmp.c \
+       $(top_srcdir)/src/daemon/lldpd.h
+fuzz_sonmp_LDADD = $(top_builddir)/src/daemon/liblldpd.la $(LDADD) $(FUZZ_DECODE_ENGINE)
+
+fuzz_edp_SOURCES = fuzz_edp.c \
+       $(top_srcdir)/src/daemon/lldpd.h
+fuzz_edp_LDADD = $(top_builddir)/src/daemon/liblldpd.la $(LDADD) $(FUZZ_DECODE_ENGINE)
+endif
+
 MOSTLYCLEANFILES = *.pcap
index 22b0aa053da8d47eaced1f5f436e6fac9194e62f..9f1932fdf23959bf24eaa830fd947bee87c732d6 100644 (file)
@@ -90,31 +90,6 @@ decode(char *frame, int size, struct lldpd_hardware *hardware,
        return decoded;
 }
 
-#ifdef FUZZ_DECODE
-
-#  define kMinInputLength 30
-#  define kMaxInputLength 1500
-
-extern int
-LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
-{
-       if (size < kMinInputLength || size > kMaxInputLength) {
-               return 0;
-       }
-       struct lldpd_hardware hardware;
-       struct lldpd_chassis *nchassis = NULL;
-       struct lldpd_port *nport = NULL;
-       if (!decode((char *)data, (int)size, &hardware, &nchassis, &nport)) {
-               return -1;
-       }
-       lldpd_port_cleanup(nport, 1);
-       free(nport);
-       lldpd_chassis_cleanup(nchassis, 1);
-       return 0;
-}
-
-#else
-
 static void
 usage(void)
 {
@@ -191,7 +166,7 @@ main(int argc, char **argv)
                if (inet_ntop(af, &mgmt->m_addr, ipaddress, alen) == NULL) break;
                printf(" mgmt: %s\n", ipaddress);
        }
-#  ifdef ENABLE_LLDPMED
+#ifdef ENABLE_LLDPMED
        printf(" MED cap: %" PRIu16 "\n", nchassis->c_med_cap_available);
        printf(" MED type: %" PRIu8 "\n", nchassis->c_med_type);
        printf(" MED HW: %s\n", nchassis->c_med_hw ? nchassis->c_med_hw : "(null)");
@@ -204,7 +179,7 @@ main(int argc, char **argv)
            nchassis->c_med_model ? nchassis->c_med_model : "(null)");
        printf(" MED asset: %s\n",
            nchassis->c_med_asset ? nchassis->c_med_asset : "(null)");
-#  endif
+#endif
 
        printf("Port:\n");
        printf(" ID subtype: %" PRIu8 "\n", nport->p_id_subtype);
@@ -212,7 +187,7 @@ main(int argc, char **argv)
        printf(" Description: %s\n", nport->p_descr ? nport->p_descr : "(null)");
        printf(" MFS: %" PRIu16 "\n", nport->p_mfs);
        printf(" TTL: %" PRIu16 "\n", nport->p_ttl);
-#  ifdef ENABLE_DOT3
+#ifdef ENABLE_DOT3
        printf(" Dot3 aggrID: %" PRIu32 "\n", nport->p_aggregid);
        printf(" Dot3 MAC/phy autoneg supported: %" PRIu8 "\n",
            nport->p_macphy.autoneg_support);
@@ -232,8 +207,8 @@ main(int argc, char **argv)
        printf(" Dot3 power priority: %" PRIu8 "\n", nport->p_power.priority);
        printf(" Dot3 power requested: %" PRIu16 "\n", nport->p_power.requested);
        printf(" Dot3 power allocated: %" PRIu16 "\n", nport->p_power.allocated);
-#  endif
-#  ifdef ENABLE_LLDPMED
+#endif
+#ifdef ENABLE_LLDPMED
        printf(" MED cap: %" PRIu16 "\n", nport->p_med_cap_enabled);
        for (int i = 0; i < LLDP_MED_APPTYPE_LAST; i++) {
                if (nport->p_med_policy[i].type == 0) continue;
@@ -259,8 +234,8 @@ main(int argc, char **argv)
        printf(" MED power source: %" PRIu8 "\n", nport->p_med_power.source);
        printf(" MED power priority: %" PRIu8 "\n", nport->p_med_power.priority);
        printf(" MED power value: %" PRIu16 "\n", nport->p_med_power.val);
-#  endif
-#  ifdef ENABLE_DOT1
+#endif
+#ifdef ENABLE_DOT1
        printf(" Dot1 PVID: %" PRIu16 "\n", nport->p_pvid);
        struct lldpd_vlan *vlan;
        TAILQ_FOREACH (vlan, &nport->p_vlans, v_entries) {
@@ -275,8 +250,8 @@ main(int argc, char **argv)
        TAILQ_FOREACH (pid, &nport->p_pids, p_entries) {
                printf(" Dot1 PI: %s\n", tohex(pid->p_pi, pid->p_pi_len));
        }
-#  endif
-#  ifdef ENABLE_CUSTOM
+#endif
+#ifdef ENABLE_CUSTOM
        struct lldpd_custom *custom;
        TAILQ_FOREACH (custom, &nport->p_custom_list, next) {
                printf(" Custom OUI: %s\n",
@@ -285,8 +260,6 @@ main(int argc, char **argv)
                printf(" Custom info: %s\n",
                    tohex((char *)custom->oui_info, custom->oui_info_len));
        }
-#  endif
+#endif
        exit(0);
 }
-
-#endif
diff --git a/tests/fuzz_cdp.c b/tests/fuzz_cdp.c
new file mode 100644 (file)
index 0000000..e0fa569
--- /dev/null
@@ -0,0 +1,54 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#include "../src/daemon/lldpd.h"
+
+#define kMinInputLength 5
+#define kMaxInputLength 2048
+
+/* Use this callback to avoid some logs */
+void donothing(int pri, const char *msg) {};
+
+extern int
+LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
+{
+       if (Size < kMinInputLength || Size > kMaxInputLength) {
+               return 1;
+       }
+
+       struct lldpd_chassis *nchassis = NULL;
+       struct lldpd_port *nport = NULL;
+       struct lldpd_hardware hardware;
+
+       log_register(donothing);
+
+       if (!cdpv2_guess((char *)Data, Size)) {
+               return 1;
+       }
+
+       cdp_decode(NULL, (char *)Data, Size, &hardware, &nchassis, &nport);
+
+       if (!nchassis || !nport) {
+               return 1;
+       }
+
+       lldpd_port_cleanup(nport, 1);
+       free(nport);
+       lldpd_chassis_cleanup(nchassis, 1);
+
+       return 0;
+}
diff --git a/tests/fuzz_edp.c b/tests/fuzz_edp.c
new file mode 100644 (file)
index 0000000..76d1253
--- /dev/null
@@ -0,0 +1,52 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#include "../src/daemon/lldpd.h"
+
+#define kMinInputLength 5
+#define kMaxInputLength 2048
+
+/* Use this callback to avoid some logs */
+void donothing(int pri, const char *msg) {};
+
+extern int
+LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
+{
+       if (Size < kMinInputLength || Size > kMaxInputLength) {
+               return 1;
+       }
+
+       struct lldpd cfg;
+       cfg.g_config.c_mgmt_pattern = NULL;
+
+       struct lldpd_chassis *nchassis = NULL;
+       struct lldpd_port *nport = NULL;
+       struct lldpd_hardware hardware;
+       log_register(donothing);
+
+       edp_decode(&cfg, (char *)Data, Size, &hardware, &nchassis, &nport);
+
+       if (!nchassis || !nport) {
+               return 1;
+       }
+
+       lldpd_port_cleanup(nport, 1);
+       free(nport);
+       lldpd_chassis_cleanup(nchassis, 1);
+
+       return 0;
+}
diff --git a/tests/fuzz_lldp.c b/tests/fuzz_lldp.c
new file mode 100644 (file)
index 0000000..62b812a
--- /dev/null
@@ -0,0 +1,50 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#include "../src/daemon/lldpd.h"
+
+#define kMinInputLength 5
+#define kMaxInputLength 2048
+
+/* Use this callback to avoid some logs */
+void donothing(int pri, const char *msg) {};
+
+extern int
+LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
+{
+       if (Size < kMinInputLength || Size > kMaxInputLength) {
+               return 1;
+       }
+
+       struct lldpd_chassis *nchassis = NULL;
+       struct lldpd_port *nport = NULL;
+       struct lldpd_hardware hardware;
+
+       log_register(donothing);
+
+       lldp_decode(NULL, (char *)Data, Size, &hardware, &nchassis, &nport);
+
+       if (!nchassis || !nport) {
+               return 1;
+       }
+
+       lldpd_port_cleanup(nport, 1);
+       free(nport);
+       lldpd_chassis_cleanup(nchassis, 1);
+
+       return 0;
+}
diff --git a/tests/fuzz_sonmp.c b/tests/fuzz_sonmp.c
new file mode 100644 (file)
index 0000000..0594673
--- /dev/null
@@ -0,0 +1,50 @@
+/* -*- mode: c; c-file-style: "openbsd" -*- */
+/*
+ * Copyright (c) 2023 Vincent Bernat <bernat@luffy.cx>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#include "../src/daemon/lldpd.h"
+
+#define kMinInputLength 5
+#define kMaxInputLength 2048
+
+/* Use this callback to avoid some logs */
+void donothing(int pri, const char *msg) {};
+
+extern int
+LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
+{
+       if (Size < kMinInputLength || Size > kMaxInputLength) {
+               return 1;
+       }
+
+       struct lldpd_chassis *nchassis = NULL;
+       struct lldpd_port *nport = NULL;
+       struct lldpd_hardware hardware;
+
+       log_register(donothing);
+
+       sonmp_decode(NULL, (char *)Data, Size, &hardware, &nchassis, &nport);
+
+       if (!nchassis || !nport) {
+               return 1;
+       }
+
+       lldpd_port_cleanup(nport, 1);
+       free(nport);
+       lldpd_chassis_cleanup(nchassis, 1);
+
+       return 0;
+}