/* ** Copyright (c) 2019 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) * ** This program 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. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** This file contains code to connect Fossil to libFuzzer. Do a web search ** for "libfuzzer" for details about that fuzzing platform. ** ** To build on linux (the only platform for which this works at ** present) first do ** ** ./configure ** ** Then edit the Makefile as follows: ** ** (1) Change CC to be "clang-6.0" or some other compiler that ** supports libFuzzer ** ** (2) Change APPNAME to "fossil-fuzz" ** ** (3) Add "-fsanitize=fuzzer" and "-DFOSSIL_FUZZ" to TCCFLAGS. Perhaps ** make the first change "-fsanitize=fuzzer,undefined,address" for ** extra, but slower, testing. ** ** Then build the fuzzer using: ** ** make clean fossil-fuzz ** ** To run the fuzzer, create a working directory ("cases"): ** ** mkdir cases ** ** Then seed the working directory with example input files. For example, ** if fuzzing the wiki formatter, perhaps copy *.wiki into cases. Then ** run the fuzzer thusly: ** ** fossil-fuzz cases ** ** The default is to fuzz the Fossil-wiki translator. Use the --fuzztype TYPE ** option to fuzz different aspects of the system. */ #include "config.h" #include "fuzz.h" #if LOCAL_INTERFACE /* ** Type of fuzzing: */ #define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */ #define FUZZ_MARKDOWN 1 /* The Markdown formatter */ #define FUZZ_ARTIFACT 2 /* Fuzz the artifact parser */ #endif /* The type of fuzzing to do */ static int eFuzzType = FUZZ_WIKI; /* The fuzzer invokes this routine once for each fuzzer input */ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ Blob in, out; blob_init(&in, 0, 0); blob_append(&in, (char*)aData, (int)nByte); blob_zero(&out); switch( eFuzzType ){ case FUZZ_WIKI: { Blob title = BLOB_INITIALIZER; wiki_convert(&in, &out, 0); blob_reset(&out); markdown_to_html(&in, &title, &out); blob_reset(&title); break; } } blob_reset(&in); blob_reset(&out); return 0; } /* ** Check fuzzer command-line options. */ static void fuzzer_options(void){ const char *zType; db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0); db_multi_exec("PRAGMA query_only=1;"); zType = find_option("fuzztype",0,1); if( zType==0 || fossil_strcmp(zType,"wiki")==0 ){ eFuzzType = FUZZ_WIKI; }else if( fossil_strcmp(zType,"markdown")==0 ){ eFuzzType = FUZZ_MARKDOWN; }else{ fossil_fatal("unknown fuzz type: \"%s\"", zType); } } /* Libfuzzer invokes this routine once prior to start-up to ** process command-line options. */ int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){ expand_args_option(*pArgc, *pArgv); fuzzer_options(); *pArgc = g.argc; *pArgv = g.argv; return 0; } /* ** COMMAND: test-fuzz ** ** Usage: %fossil test-fuzz [-type TYPE] INPUTFILE... ** ** Run a fuzz test using INPUTFILE as the test data. TYPE can be one of: ** ** wiki Fuzz the Fossil-wiki translator ** markdown Fuzz the markdown translator ** artifact Fuzz the artifact parser */ void fuzz_command(void){ Blob in; int i; fuzzer_options(); verify_all_options(); for(i=2; i