| diff --git a/configure.ac b/configure.ac |
| index 7b398f3df..ee69b3063 100644 |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -991,6 +991,15 @@ if test x"$use_tofu" = xyes ; then |
| fi |
| fi |
| |
| +# TODO choose when to build fuzzing with option ? |
| +AC_CHECK_LIB(FuzzingEngine, main, |
| + [ LIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" |
| + have_fuzz=yes |
| + ]) |
| +AC_SUBST(LIB_FUZZING_ENGINE) |
| +AC_CHECK_PROG(HAVE_CLANGXX, clang++, 1) |
| +AM_CONDITIONAL(HAVE_LIB_FUZZING_ENGINE, [test "$have_fuzz" = yes -a "$HAVE_CLANGXX" = 1]) |
| + |
| AM_CONDITIONAL(SQLITE3, test "$have_sqlite" = "yes") |
| |
| if test x"$use_tofu" = xyes ; then |
| @@ -2149,6 +2158,7 @@ tests/migrations/Makefile |
| tests/tpm2dtests/Makefile |
| tests/gpgme/Makefile |
| tests/pkits/Makefile |
| +tests/fuzz/Makefile |
| g10/gpg.w32-manifest |
| tools/gpg-connect-agent.w32-manifest |
| tools/gpgconf.w32-manifest |
| diff --git a/g10/Makefile.am b/g10/Makefile.am |
| index eb23573b7..785ac2b4b 100644 |
| --- a/g10/Makefile.am |
| +++ b/g10/Makefile.am |
| @@ -47,6 +47,7 @@ endif |
| # NB: We use noinst_ for gpg and gpgv so that we can install them with |
| # the install-hook target under the name gpg2/gpgv2. |
| noinst_PROGRAMS = gpg |
| +noinst_LIBRARIES = libgpg.a |
| if !HAVE_W32CE_SYSTEM |
| noinst_PROGRAMS += gpgv |
| endif |
| @@ -164,6 +165,9 @@ gpg_sources = server.c \ |
| gpg_SOURCES = gpg.c \ |
| keyedit.c keyedit.h \ |
| $(gpg_sources) |
| +libgpg_a_SOURCES = keyedit.c keyedit.h \ |
| + $(gpg_sources) |
| + |
| |
| gpgv_SOURCES = gpgv.c \ |
| $(common_source) \ |
| diff --git a/g10/armor.c b/g10/armor.c |
| index eb2d28bca..594f5bd2d 100644 |
| --- a/g10/armor.c |
| +++ b/g10/armor.c |
| @@ -313,7 +313,9 @@ static void |
| invalid_armor(void) |
| { |
| write_status(STATUS_BADARMOR); |
| +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| g10_exit(1); /* stop here */ |
| +#endif |
| } |
| |
| |
| diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h |
| index c0f1e0cec..52652a0e0 100644 |
| --- a/g10/call-dirmngr.h |
| +++ b/g10/call-dirmngr.h |
| @@ -19,6 +19,8 @@ |
| #ifndef GNUPG_G10_CALL_DIRMNGR_H |
| #define GNUPG_G10_CALL_DIRMNGR_H |
| |
| +#include "options.h" |
| + |
| void gpg_dirmngr_deinit_session_data (ctrl_t ctrl); |
| |
| gpg_error_t gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver); |
| diff --git a/g10/compress-bz2.c b/g10/compress-bz2.c |
| index 45aa40dfc..1a74a89d7 100644 |
| --- a/g10/compress-bz2.c |
| +++ b/g10/compress-bz2.c |
| @@ -155,8 +155,15 @@ do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs, |
| (unsigned)bzs->avail_in, (unsigned)bzs->avail_out, zrc); |
| if( zrc == BZ_STREAM_END ) |
| rc = -1; /* eof */ |
| - else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR ) |
| - log_fatal("bz2lib inflate problem: rc=%d\n", zrc ); |
| + else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR ) { |
| +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| + log_error("bz2lib inflate problem: rc=%d\n", zrc ); |
| + rc = GPG_ERR_BAD_DATA; |
| + break; |
| +#else |
| + log_fatal("bz2lib inflate problem: rc=%d\n", zrc ); |
| +#endif |
| + } |
| else if (zrc == BZ_OK && eofseen |
| && !bzs->avail_in && bzs->avail_out > 0) |
| { |
| diff --git a/g10/compress.c b/g10/compress.c |
| index e7a6f2b11..9a9ab5460 100644 |
| --- a/g10/compress.c |
| +++ b/g10/compress.c |
| @@ -204,10 +204,19 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, |
| if( zrc == Z_STREAM_END ) |
| rc = -1; /* eof */ |
| else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) { |
| +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| + rc = -1; |
| + zrc = Z_BUF_ERROR; |
| + if( zs->msg ) |
| + log_error("zlib inflate problem: %s\n", zs->msg ); |
| + else |
| + log_error("zlib inflate problem: rc=%d\n", zrc ); |
| +#else |
| if( zs->msg ) |
| log_fatal("zlib inflate problem: %s\n", zs->msg ); |
| else |
| log_fatal("zlib inflate problem: rc=%d\n", zrc ); |
| +#endif |
| } |
| } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR |
| && !leave); |
| diff --git a/g10/parse-packet.c b/g10/parse-packet.c |
| index bb05eabb7..638d895d0 100644 |
| --- a/g10/parse-packet.c |
| +++ b/g10/parse-packet.c |
| @@ -806,7 +806,12 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos, |
| * the uncompressing layer - in some error cases it just loops |
| * and spits out 0xff bytes. */ |
| log_error ("%s: garbled packet detected\n", iobuf_where (inp)); |
| +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| + rc = gpg_error (GPG_ERR_INV_PACKET); |
| + goto leave; |
| +#else |
| g10_exit (2); |
| +#endif |
| } |
| |
| if (out && pkttype) |
| diff --git a/g10/plaintext.c b/g10/plaintext.c |
| index 3e169d93f..aa83ffbe0 100644 |
| --- a/g10/plaintext.c |
| +++ b/g10/plaintext.c |
| @@ -617,10 +617,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2, |
| |
| if (!fp) |
| { |
| +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| + errno = ENOENT; |
| + rc = gpg_error_from_syserror (); |
| + goto leave; |
| +#else |
| if (opt.verbose) |
| log_info (_("reading stdin ...\n")); |
| fp = iobuf_open (NULL); |
| log_assert (fp); |
| +#endif |
| } |
| do_hash (md, md2, fp, textmode); |
| iobuf_close (fp); |
| diff --git a/g10/sig-check.c b/g10/sig-check.c |
| index 8dd18b2e2..9f5db89f9 100644 |
| --- a/g10/sig-check.c |
| +++ b/g10/sig-check.c |
| @@ -783,8 +783,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) |
| { |
| gcry_md_hd_t md; |
| |
| - if (gcry_md_open (&md, sig->digest_algo, 0)) |
| - BUG (); |
| + rc = gcry_md_open (&md, sig->digest_algo, 0); |
| + if (rc) |
| + return rc; |
| hash_public_key(md,pk); |
| /* Note: check_signature only checks that the signature |
| is good. It does not fail if the key is revoked. */ |
| diff --git a/tests/Makefile.am b/tests/Makefile.am |
| index f29b68a53..e788c9916 100644 |
| --- a/tests/Makefile.am |
| +++ b/tests/Makefile.am |
| @@ -24,7 +24,13 @@ else |
| tpm2dtests = |
| endif |
| |
| -SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) . |
| +SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) |
| + |
| +if MAINTAINER_MODE |
| +SUBDIRS += fuzz |
| +endif |
| + |
| +SUBDIRS += . |
| |
| GPGSM = ../sm/gpgsm |
| |
| diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am |
| new file mode 100644 |
| index 000000000..eb2216d3e |
| --- /dev/null |
| +++ b/tests/fuzz/Makefile.am |
| @@ -0,0 +1,84 @@ |
| +# Makefile.am - For tests/fuzz |
| +# Copyright (C) 2018 Free Software Foundation, Inc. |
| +# |
| +# This file is part of GnuPG. |
| +# |
| +# GnuPG is free software; you can redistribute it and/or modify |
| +# it under the terms of the GNU General Public License as published by |
| +# the Free Software Foundation; either version 3 of the License, or |
| +# (at your option) any later version. |
| +# |
| +# GnuPG 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 General Public License for more details. |
| +# |
| +# You should have received a copy of the GNU General Public License |
| +# along with this program; if not, see <https://www.gnu.org/licenses/>. |
| +# Process this file with automake to create Makefile.in |
| + |
| + |
| +# Programs required before we can run these tests. |
| +required_pgms = ../../g10/gpg$(EXEEXT) |
| + |
| + |
| +# Force linking with clang++ even if we have pure C fuzzing targets |
| +CCLD = clang++ |
| +AM_LDFLAGS = -stdlib=libc++ |
| + |
| +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/g10 |
| +include $(top_srcdir)/am/cmacros.am |
| + |
| +noinst_PROGRAMS = fuzz_verify fuzz_import fuzz_decrypt fuzz_list |
| + |
| +fuzz_verify_SOURCES = fuzz_verify.c |
| + |
| +fuzz_verify_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE) \ |
| + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ |
| + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ |
| + $(LIBICONV) $(resource_objs) $(extra_sys_libs) |
| + |
| +fuzz_verify_DEPENDENCIES = fuzz_verify_seed_corpus.zip |
| + |
| +fuzz_verify_seed_corpus.zip: |
| + cd .. && zip -r fuzz/fuzz_verify_seed_corpus.zip openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* openpgp/samplemsgs/* |
| + |
| +fuzz_import_SOURCES = fuzz_import.c |
| + |
| +fuzz_import_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ |
| + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ |
| + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ |
| + $(LIBICONV) $(resource_objs) $(extra_sys_libs) |
| + |
| +fuzz_import_DEPENDENCIES = fuzz_import_seed_corpus.zip |
| + |
| +fuzz_import_seed_corpus.zip: |
| + cd .. && zip -r fuzz/fuzz_import_seed_corpus.zip openpgp/samplekeys/* openpgp/key-selection/* openpgp/*.asc openpgp/trust-pgp/*.asc openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* |
| + |
| +fuzz_decrypt_SOURCES = fuzz_decrypt.c |
| + |
| +fuzz_decrypt_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ |
| + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ |
| + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ |
| + $(LIBICONV) $(resource_objs) $(extra_sys_libs) |
| + |
| +fuzz_decrypt_DEPENDENCIES = fuzz_decrypt_seed_corpus.zip |
| + |
| +fuzz_decrypt_seed_corpus.zip: |
| + cd .. && zip -r fuzz/fuzz_decrypt_seed_corpus.zip openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* openpgp/samplemsgs/* |
| + |
| +fuzz_list_SOURCES = fuzz_list.c |
| + |
| +fuzz_list_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ |
| +$(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ |
| +$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ |
| +$(LIBICONV) $(resource_objs) $(extra_sys_libs) |
| + |
| +fuzz_list_DEPENDENCIES = fuzz_list_seed_corpus.zip |
| + |
| +fuzz_list_seed_corpus.zip: |
| + cd .. && zip -r fuzz/fuzz_list_seed_corpus.zip openpgp/ |
| + |
| +# We need to depend on a couple of programs so that the tests don't |
| +# start before all programs are built. |
| +all-local: $(required_pgms) |