Fossil SCM

fossil-scm / src / fuzz.c
Blame History Raw 172 lines
1
/*
2
** Copyright (c) 2019 D. Richard Hipp
3
**
4
** This program is free software; you can redistribute it and/or
5
** modify it under the terms of the Simplified BSD License (also
6
** known as the "2-Clause License" or "FreeBSD License".)
7
*
8
** This program is distributed in the hope that it will be useful,
9
** but without any warranty; without even the implied warranty of
10
** merchantability or fitness for a particular purpose.
11
**
12
** Author contact information:
13
** [email protected]
14
** http://www.hwaci.com/drh/
15
**
16
*******************************************************************************
17
**
18
** This file contains code to connect Fossil to libFuzzer. Do a web search
19
** for "libfuzzer" for details about that fuzzing platform.
20
**
21
** To build on linux (the only platform for which this works at
22
** present) first do
23
**
24
** ./configure
25
**
26
** Then edit the Makefile as follows:
27
**
28
** (1) Change CC to be "clang-6.0" or some other compiler that
29
** supports libFuzzer
30
**
31
** (2) Change APPNAME to "fossil-fuzz"
32
**
33
** (3) Add "-fsanitize=fuzzer" and "-DFOSSIL_FUZZ" to TCCFLAGS. Perhaps
34
** make the first change "-fsanitize=fuzzer,undefined,address" for
35
** extra, but slower, testing.
36
**
37
** Then build the fuzzer using:
38
**
39
** make clean fossil-fuzz
40
**
41
** To run the fuzzer, create a working directory ("cases"):
42
**
43
** mkdir cases
44
**
45
** Then seed the working directory with example input files. For example,
46
** if fuzzing the wiki formatter, perhaps copy *.wiki into cases. Then
47
** run the fuzzer thusly:
48
**
49
** fossil-fuzz cases
50
**
51
** The default is to fuzz the Fossil-wiki translator. Use the --fuzztype TYPE
52
** option to fuzz different aspects of the system.
53
*/
54
#include "config.h"
55
#include "fuzz.h"
56
57
#if LOCAL_INTERFACE
58
/*
59
** Type of fuzzing:
60
*/
61
#define FUZZ_WIKI 0 /* The Fossil-Wiki formatter */
62
#define FUZZ_MARKDOWN 1 /* The Markdown formatter */
63
#define FUZZ_ARTIFACT 2 /* Fuzz the artifact parser */
64
#define FUZZ_WIKI2 3 /* FOSSIL_WIKI and FOSSIL_MARKDOWN */
65
#define FUZZ_COMFORMAT 4 /* comment_print() */
66
#endif
67
68
/* The type of fuzzing to do */
69
static int eFuzzType = FUZZ_WIKI;
70
71
/* The fuzzer invokes this routine once for each fuzzer input
72
*/
73
int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
74
Blob in, out;
75
blob_init(&in, 0, 0);
76
blob_append(&in, (char*)aData, (int)nByte);
77
blob_zero(&out);
78
switch( eFuzzType ){
79
case FUZZ_WIKI: {
80
wiki_convert(&in, &out, 0);
81
blob_reset(&out);
82
break;
83
}
84
case FUZZ_MARKDOWN: {
85
Blob title = BLOB_INITIALIZER;
86
blob_reset(&out);
87
markdown_to_html(&in, &title, &out);
88
blob_reset(&title);
89
break;
90
}
91
case FUZZ_WIKI2: {
92
Blob title = BLOB_INITIALIZER;
93
wiki_convert(&in, &out, 0);
94
blob_reset(&out);
95
markdown_to_html(&in, &title, &out);
96
blob_reset(&title);
97
break;
98
}
99
case FUZZ_ARTIFACT: {
100
fossil_fatal("FUZZ_ARTIFACT is not implemented.");
101
break;
102
}
103
case FUZZ_COMFORMAT: {
104
if( nByte>=3 && aData[1]!=0 && memchr(&aData[1], 0, nByte-1)!=0 ){
105
int flags = (int)aData[0];
106
comment_print((const char*)&aData[1],0,15,80,flags);
107
}
108
}
109
}
110
blob_reset(&in);
111
blob_reset(&out);
112
return 0;
113
}
114
115
/*
116
** Check fuzzer command-line options.
117
*/
118
static void fuzzer_options(void){
119
const char *zType;
120
db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
121
db_multi_exec("PRAGMA query_only=1;");
122
zType = find_option("fuzztype",0,1);
123
if( zType==0 || fossil_strcmp(zType,"wiki")==0 ){
124
eFuzzType = FUZZ_WIKI;
125
}else if( fossil_strcmp(zType,"markdown")==0 ){
126
eFuzzType = FUZZ_MARKDOWN;
127
}else if( fossil_strcmp(zType,"wiki2")==0 ){
128
eFuzzType = FUZZ_WIKI2;
129
}else if( fossil_strcmp(zType,"comformat")==0 ){
130
eFuzzType = FUZZ_COMFORMAT;
131
}else{
132
fossil_fatal("unknown fuzz type: \"%s\"", zType);
133
}
134
}
135
136
/* Libfuzzer invokes this routine once prior to start-up to
137
** process command-line options.
138
*/
139
int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
140
expand_args_option(*pArgc, *pArgv);
141
fuzzer_options();
142
*pArgc = g.argc;
143
*pArgv = g.argv;
144
return 0;
145
}
146
147
/*
148
** COMMAND: test-fuzz
149
**
150
** Usage: %fossil test-fuzz [-fuzztype TYPE] INPUTFILE...
151
**
152
** Run a fuzz test using INPUTFILE as the test data. TYPE can be one of:
153
**
154
** comformat Fuzz the comment_print() routine
155
** wiki Fuzz the Fossil-wiki translator
156
** markdown Fuzz the markdown translator
157
** artifact Fuzz the artifact parser
158
** wiki2 Fuzz the Fossil-wiki and markdown translator
159
*/
160
void fuzz_command(void){
161
Blob in;
162
int i;
163
fuzzer_options();
164
verify_all_options();
165
for(i=2; i<g.argc; i++){
166
blob_read_from_file(&in, g.argv[i], ExtFILE);
167
LLVMFuzzerTestOneInput((const uint8_t*)in.aData, (size_t)in.nUsed);
168
fossil_print("%s\n", g.argv[i]);
169
blob_reset(&in);
170
}
171
}
172

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button