@@ -56,6 +56,14 @@ def main():
56
56
'--m_dir' ,
57
57
help = 'Merge inputs from this directory into the seed_dir. Needs /target subdirectory.' ,
58
58
)
59
+ parser .add_argument (
60
+ '-g' ,
61
+ '--generate' ,
62
+ action = 'store_true' ,
63
+ help = 'Create new corpus seeds (or extend the existing ones) by running'
64
+ ' the given targets for a finite number of times. Outputs them to'
65
+ ' the passed seed_dir.'
66
+ )
59
67
60
68
args = parser .parse_args ()
61
69
@@ -100,19 +108,20 @@ def main():
100
108
101
109
logging .info ("{} of {} detected fuzz target(s) selected: {}" .format (len (test_list_selection ), len (test_list_all ), " " .join (test_list_selection )))
102
110
103
- test_list_seedless = []
104
- for t in test_list_selection :
105
- corpus_path = os .path .join (args .seed_dir , t )
106
- if not os .path .exists (corpus_path ) or len (os .listdir (corpus_path )) == 0 :
107
- test_list_seedless .append (t )
108
- test_list_seedless .sort ()
109
- if test_list_seedless :
110
- logging .info (
111
- "Fuzzing harnesses lacking a seed corpus: {}" .format (
112
- " " .join (test_list_seedless )
111
+ if not args .generate :
112
+ test_list_seedless = []
113
+ for t in test_list_selection :
114
+ corpus_path = os .path .join (args .seed_dir , t )
115
+ if not os .path .exists (corpus_path ) or len (os .listdir (corpus_path )) == 0 :
116
+ test_list_seedless .append (t )
117
+ test_list_seedless .sort ()
118
+ if test_list_seedless :
119
+ logging .info (
120
+ "Fuzzing harnesses lacking a seed corpus: {}" .format (
121
+ " " .join (test_list_seedless )
122
+ )
113
123
)
114
- )
115
- logging .info ("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets" )
124
+ logging .info ("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets" )
116
125
117
126
try :
118
127
help_output = subprocess .run (
@@ -133,6 +142,14 @@ def main():
133
142
sys .exit (1 )
134
143
135
144
with ThreadPoolExecutor (max_workers = args .par ) as fuzz_pool :
145
+ if args .generate :
146
+ return generate_corpus_seeds (
147
+ fuzz_pool = fuzz_pool ,
148
+ build_dir = config ["environment" ]["BUILDDIR" ],
149
+ seed_dir = args .seed_dir ,
150
+ targets = test_list_selection ,
151
+ )
152
+
136
153
if args .m_dir :
137
154
merge_inputs (
138
155
fuzz_pool = fuzz_pool ,
@@ -152,6 +169,37 @@ def main():
152
169
)
153
170
154
171
172
+ def generate_corpus_seeds (* , fuzz_pool , build_dir , seed_dir , targets ):
173
+ """Generates new corpus seeds.
174
+
175
+ Run {targets} without input, and outputs the generated corpus seeds to
176
+ {seed_dir}.
177
+ """
178
+ logging .info ("Generating corpus seeds to {}" .format (seed_dir ))
179
+
180
+ def job (command ):
181
+ logging .debug ("Running '{}'\n " .format (" " .join (command )))
182
+ logging .debug ("Command '{}' output:\n '{}'\n " .format (
183
+ ' ' .join (command ),
184
+ subprocess .run (command , check = True , stderr = subprocess .PIPE ,
185
+ universal_newlines = True ).stderr
186
+ ))
187
+
188
+ futures = []
189
+ for target in targets :
190
+ target_seed_dir = os .path .join (seed_dir , target )
191
+ os .makedirs (target_seed_dir , exist_ok = True )
192
+ command = [
193
+ os .path .join (build_dir , "src" , "test" , "fuzz" , target ),
194
+ "-runs=100000" ,
195
+ target_seed_dir ,
196
+ ]
197
+ futures .append (fuzz_pool .submit (job , command ))
198
+
199
+ for future in as_completed (futures ):
200
+ future .result ()
201
+
202
+
155
203
def merge_inputs (* , fuzz_pool , corpus , test_list , build_dir , merge_dir ):
156
204
logging .info ("Merge the inputs in the passed dir into the seed_dir. Passed dir {}" .format (merge_dir ))
157
205
jobs = []
0 commit comments