Skip to content

Commit

Permalink
build: add oss-fuzz support
Browse files Browse the repository at this point in the history
  • Loading branch information
flatcap committed Nov 28, 2021
1 parent 3429205 commit 6b89316
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ docs/makedoc
neomutt
pgpewrap
test/neomutt-test
fuzz/address-fuzz

# Build products
*.o
Expand Down
3 changes: 3 additions & 0 deletions Makefile.autosetup
Original file line number Diff line number Diff line change
Expand Up @@ -822,5 +822,8 @@ coverage: all test
@if ENABLE_UNIT_TESTS
@include @srcdir@/test/Makefile.autosetup
@endif
@if ENABLE_FUZZ_TESTS
@include @srcdir@/fuzz/Makefile.autosetup
@endif

# vim: set ts=8 noexpandtab:
10 changes: 9 additions & 1 deletion auto.def
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ options {
asan=0 => "Enable the Address Sanitizer"
coverage=0 => "Enable Coverage Testing"
testing=0 => "Enable Unit Testing"
fuzzing => "Enable Fuzz Testing"
# Configure with pkg-config
pkgconf=0 => "Use pkg-config during configure"
# Enable all options
Expand Down Expand Up @@ -150,7 +151,7 @@ if {1} {
# Keep sorted, please.
foreach opt {
asan autocrypt bdb coverage debug-backtrace debug-email debug-graphviz debug-notify
debug-parse-test debug-window doc everything fmemopen full-doc gdbm gnutls
debug-parse-test debug-window doc everything fmemopen full-doc fuzzing gdbm gnutls
gpgme gss homespool idn idn2 include-path-in-cflags inotify kyotocabinet
lmdb locales-fix lua lz4 mixmaster nls notmuch pcre2 pgp pkgconf qdbm
rocksdb sasl smime sqlite ssl testing tdb tokyocabinet zlib zstd
Expand Down Expand Up @@ -611,6 +612,13 @@ if {[get-define want-testing]} {
lappend subdirs test
}

###############################################################################
# Fuzz Testing
if {[get-define want-fuzzing]} {
define ENABLE_FUZZ_TESTS
lappend subdirs fuzz
}

###############################################################################
# Lua
if {[get-define want-lua]} {
Expand Down
24 changes: 24 additions & 0 deletions fuzz/Makefile.autosetup
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FUZZ_OBJS = fuzz/address.o

CFLAGS += -I$(SRCDIR)/fuzz

FUZZ_ADDRESS = fuzz/address-fuzz$(EXEEXT)

.PHONY: fuzz
fuzz: $(FUZZ_ADDRESS)

$(FUZZ_ADDRESS): $(FUZZ_OBJS) $(NEOMUTTOBJS) $(MUTTLIBS) $(NEOMUTTLIBS)
$(CXX) $(CXXFLAGS) -o $@ $(FUZZ_OBJS) $(NEOMUTTOBJS) $(MUTTLIBS) $(NEOMUTTLIBS) $(LDFLAGS) $(LIBS) $(LIB_FUZZING_ENGINE)

all-fuzz: $(FUZZ_ADDRESS)

clean-fuzz:
$(RM) $(FUZZ_ADDRESS) $(FUZZ_OBJS) $(FUZZ_OBJS:.o=.Po)

install-fuzz:
uninstall-fuzz:

FUZZ_DEPFILES = $(FUZZ_OBJS:.o=.Po)
-include $(FUZZ_DEPFILES)

# vim: set ts=8 noexpandtab:
59 changes: 59 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Fuzzing NeoMutt

NeoMutt has some support for Fuzzing.

- https://en.wikipedia.org/wiki/Fuzzing

It's currently limited to two functions.
Two that could be susceptible to remote attacks.

- `mutt_rfc822_read_header();`
- `mutt_parse_part();`

The fuzzing machinery uses a custom entry point to the code.
This can be found in `fuzz/address.c`

```c
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
```
### Build the Fuzzer
To build the fuzzer, we need to build with `clang` and pass some extra flags:
```sh
# Set some environment variables
export EXTRA_CFLAGS="-fsanitize=fuzzer"
export CXXFLAGS="$EXTRA_CFLAGS"
```

```sh
# Configure and build
./configure CC=clang --disable-doc --quiet --fuzzing
make CC=clang CXX=clang fuzz
```

### Run the Fuzzer

The fuzzer can be run by simply:

```sh
fuzz/address-fuzz
```

or it can be run against our corpus of test cases:

```sh
# Run the fuzzer on the sample data
git clone https://github.com/neomutt/corpus-address.git
fuzz/address-fuzz corpus-address
```

To see some more options, run:

```sh
fuzz/address-fuzz -help=1
```

Adding the option `-max_total_time=3600` will limit the run time to one hour.

41 changes: 41 additions & 0 deletions fuzz/address.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "mutt/logging.h"
#include "config/set.h"
#include "email/body.h"
#include "email/email.h"
#include "email/envelope.h"
#include "email/mime.h"
#include "email/parse.h"
#include "core/neomutt.h"
#include "init.h"
#include "options.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
MuttLogger = log_disp_null;
struct ConfigSet *cs = cs_new(16);
NeoMutt = neomutt_new(cs);
init_config(cs);
OptNoCurses = 1;
char file[] = "/tmp/mutt-fuzz";
FILE *fp = fopen(file, "wb");
if (fp != NULL)
{
fwrite(data, 1, size, fp);
fclose(fp);
}
fp = fopen(file, "rb");
struct Email *e = email_new();
struct Envelope *env = mutt_rfc822_read_header(fp, e, 0, 0);
mutt_parse_part(fp, e->body);
email_free(&e);
mutt_env_free(&env);
fclose(fp);
neomutt_free(&NeoMutt);
cs_free(&cs);
return 0;
}
8 changes: 8 additions & 0 deletions init.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@
#ifdef USE_IMAP
#include "imap/lib.h"
#endif
#ifdef USE_AUTOCRYPT
#include "autocrypt/lib.h"
#else
static inline bool config_init_autocrypt(struct ConfigSet *cs)
{
return true;
}
#endif

/* Initial string that starts completion. No telling how much the user has
* typed so far. Allocate 1024 just to be sure! */
Expand Down
8 changes: 7 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,13 @@ static void log_translation(void)
* @retval 0 Success
* @retval 1 Error
*/
int main(int argc, char *argv[], char *envp[])
int
#ifdef ENABLE_FUZZ_TESTS
disabled_main
#else
main
#endif
(int argc, char *argv[], char *envp[])
{
char *subject = NULL;
char *include_file = NULL;
Expand Down
3 changes: 3 additions & 0 deletions ncrypt/crypt_gpgme.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
#ifdef USE_AUTOCRYPT
#include "autocrypt/lib.h"
#endif
#ifdef ENABLE_NLS
#include <libintl.h>
#endif

// clang-format off
/* Values used for comparing addresses. */
Expand Down

0 comments on commit 6b89316

Please sign in to comment.