Add libtasn1_encoding_fuzzer [skip ci] Signed-off-by: Tim Rühsen <tim.ruehsen@gmx.de>
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index b215b6c..7b626e3 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am
@@ -32,7 +32,8 @@ FUZZERS = \ libtasn1_array2tree_fuzzer$(EXEEXT) \ - libtasn1_parser2tree_fuzzer$(EXEEXT) + libtasn1_parser2tree_fuzzer$(EXEEXT) \ + libtasn1_encoding_fuzzer$(EXEEXT) if FUZZING # fuzzing mode, enabled with ./configure --enable-fuzzing @@ -51,6 +52,7 @@ libtasn1_array2tree_fuzzer_SOURCES = libtasn1_array2tree_fuzzer.c $(MAIN) libtasn1_parser2tree_fuzzer_SOURCES = libtasn1_parser2tree_fuzzer.c $(MAIN) +libtasn1_encoding_fuzzer_SOURCES = libtasn1_encoding_fuzzer.c $(MAIN) # comment out below to exclude directories/files from the tarball dist-hook:
diff --git a/fuzz/libtasn1_encoding_fuzzer.c b/fuzz/libtasn1_encoding_fuzzer.c new file mode 100644 index 0000000..b1dadca --- /dev/null +++ b/fuzz/libtasn1_encoding_fuzzer.c
@@ -0,0 +1,119 @@ +/* + * Copyright(c) 2019 Free Software Foundation, Inc. + * + * This file is part of libtasn1. + * + * Libtasn1 is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Libtasn1 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libtasn1. If not, see <https://www.gnu.org/licenses/>. + * + * This fuzzer is testing the combination of asn1_parser2tree(), + * asn1_create_element(), asn1_write_value(), asn1_der_coding() and + * asn1_der_decoding() with arbitrary input data. + * + * This is a test for robustness, not for functionality. + */ + +#include <config.h> + +#include <assert.h> // assert +#include <stdlib.h> // malloc, free +#include <string.h> // strcmp, memcpy + +#include "libtasn1.h" +#include "fuzzer.h" + +static const uint8_t *g_data; +static size_t g_size; + +#if defined HAVE_DLFCN_H && defined HAVE_FMEMOPEN +#include <dlfcn.h> +#ifdef RTLD_NEXT /* Not defined e.g. on CygWin */ + +FILE *fopen(const char *pathname, const char *mode) { + FILE * (*libc_fopen)(const char *, const char *) = + (FILE * (*)(const char *, const char *)) dlsym(RTLD_NEXT, "fopen"); + + if (!strcmp(pathname, "pkix.asn")) + return fmemopen((void *) g_data, g_size, mode); + + return libc_fopen(pathname, mode); +} +#endif +#endif + +uint8_t der[256]; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + asn1_node definitions = NULL; + asn1_node asn1_element = NULL; + uint8_t *value = NULL, *value0 = NULL; + + if (size > 2048) // same as max_len = 1000 in .options file + return 0; + + g_data = data; + g_size = size; + + int rc = asn1_parser2tree("pkix.asn", &definitions, errorDescription); + if (rc != ASN1_SUCCESS) + return 0; + + rc = asn1_create_element(definitions, "TEST_TREE.Koko", &asn1_element); + if (rc != ASN1_SUCCESS) + goto out; + + size_t vlen = size <= 32 ? size : 32; + value = malloc(vlen); + assert(value); + memcpy(value, data, vlen); + + size_t vlen0 = vlen ? vlen - 1 : 0; + value0 = malloc(vlen0 + 1); + assert(value0); + memcpy(value0, data, vlen0); + value0[vlen0] = 0; + + asn1_write_value(asn1_element, "seqint", value0, 0); + asn1_write_value(asn1_element, "seqint", value, vlen); + asn1_write_value(asn1_element, "seqint.?LAST", value0, 0); + asn1_write_value(asn1_element, "seqint.?LAST", value, vlen); + asn1_write_value(asn1_element, "int", value0, 0); + asn1_write_value(asn1_element, "int", value, vlen); + asn1_write_value(asn1_element, "str", value0, 0); + asn1_write_value(asn1_element, "str", value, vlen); + asn1_write_value(asn1_element, "a", value0, 0); + asn1_write_value(asn1_element, "a", value, vlen); + asn1_write_value(asn1_element, "b", value0, 0); + asn1_write_value(asn1_element, "b", value, vlen); + asn1_write_value(asn1_element, "c", value0, 0); + asn1_write_value(asn1_element, "c", value, vlen); + asn1_write_value(asn1_element, "exp", value0, 0); + asn1_write_value(asn1_element, "exp", value, vlen); + + asn1_delete_structure(&definitions); + + int der_size = sizeof(der); + if (asn1_der_coding(asn1_element, "", der, &der_size, NULL) != ASN1_SUCCESS) + goto out; + + asn1_der_decoding(&asn1_element, der, der_size, NULL); + +out: + asn1_delete_structure(&asn1_element); + asn1_delete_structure(&definitions); + free(value0); + free(value); + return 0; +}
diff --git a/fuzz/libtasn1_encoding_fuzzer.dict b/fuzz/libtasn1_encoding_fuzzer.dict new file mode 100644 index 0000000..7ea7bca --- /dev/null +++ b/fuzz/libtasn1_encoding_fuzzer.dict
@@ -0,0 +1,29 @@ +"TEST_TREE.Koko" +"TRUE" +"FALSE" +"a" +"b" +"c" +"exp" +"str" +"int" +"seqint" +"?LAST" +"seqint.?LAST" +"TEST_TREE" +"DEFINITIONS" +"IMPLICIT" +"TAGS" +"::=" +"BEGIN" +"END" +"Koko" +"SEQUENCE" +"OF" +"INTEGER" +"OCTET" +"STRING" +"EXPLICIT" +"OPTIONAL" +"[0]" +"[10]"
diff --git a/fuzz/libtasn1_encoding_fuzzer.in/Test_encoding.asn b/fuzz/libtasn1_encoding_fuzzer.in/Test_encoding.asn new file mode 100644 index 0000000..e3c163c --- /dev/null +++ b/fuzz/libtasn1_encoding_fuzzer.in/Test_encoding.asn
@@ -0,0 +1,13 @@ +TEST_TREE { } +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +Koko ::= SEQUENCE { + seqint SEQUENCE OF INTEGER, + int INTEGER, + a [1] OCTET STRING, + b [10] OCTET STRING, + c [100] OCTET STRING, + exp [3] EXPLICIT OCTET STRING OPTIONAL, + str OCTET STRING +} +END
diff --git a/fuzz/libtasn1_encoding_fuzzer.in/oom-3f825c1dc37e6ec1784e46878612e7e1c6d2310a b/fuzz/libtasn1_encoding_fuzzer.in/oom-3f825c1dc37e6ec1784e46878612e7e1c6d2310a new file mode 100644 index 0000000..c6e2b77 --- /dev/null +++ b/fuzz/libtasn1_encoding_fuzzer.in/oom-3f825c1dc37e6ec1784e46878612e7e1c6d2310a
@@ -0,0 +1,7 @@ +TEST_TREE { } +DEFINITIONS IMPLICIT TAGS ::= +BEGIN +Koko ::= SEQUENCE { + x ?L +} +END