4 # 1) Update the 'decls' list below with your fuzzing configuration.
5 # 2) Run with the clang binary as the command-line argument.
7 from __future__
import absolute_import
, division
, print_function
17 def __init__(self
, text
, depends
=[], provides
=[], conflicts
=[]):
19 self
.depends
= depends
20 self
.provides
= provides
21 self
.conflicts
= conflicts
23 def valid(self
, model
):
24 for i
in self
.depends
:
25 if i
not in model
.decls
:
27 for i
in self
.conflicts
:
32 def apply(self
, model
, name
):
33 for i
in self
.provides
:
35 model
.source
+= self
.text
% {'name': name
}
38 Decl('struct X { int n; };\n', provides
=['X'], conflicts
=['X']),
39 Decl('static_assert(X{.n=1}.n == 1, "");\n', depends
=['X']),
40 Decl('X %(name)s;\n', depends
=['X']),
48 def write(self
, path
, contents
):
49 self
.fs
[path
] = contents
52 for f
, s
in self
.fs
.items():
53 if self
.prevfs
.get(f
) != s
:
62 self
.prevfs
, self
.fs
= self
.fs
, {}
66 class CodeModel(object):
75 return 'n' + str(self
.i
)
78 fs
.write('module.modulemap',
79 ''.join('module %s { header "%s.h" export * }\n' % (m
, m
)
80 for m
in self
.modules
.keys()))
82 for m
, (s
, _
) in self
.modules
.items():
83 fs
.write('%s.h' % m
, s
)
85 fs
.write('main.cc', self
.source
)
88 return subprocess
.call([clang
, '-std=c++11', '-c', '-fmodules', 'main.cc', '-o', '/dev/null']) != 0
95 for d
in mutations(model
):
100 except KeyboardInterrupt:
104 sys
.stdout
.write('\nReducing:\n')
109 assert m
, 'got a failure with no steps; broken clang binary?'
110 i
= random
.choice(list(range(len(m
))))
119 sys
.stdout
.write('.')
121 except KeyboardInterrupt:
122 # FIXME: Clean out output directory first.
128 i
= int(random
.uniform(0, len(options
) + none_opts
))
129 if i
>= len(options
):
133 def mutations(model
):
134 options
= [create_module
, add_top_level_decl
]
135 for opt
in choose(options
):
136 yield opt(model
, options
)
138 def create_module(model
, options
):
139 n
= model
.make_name()
141 model
.modules
[n
] = (model
.source
, model
.decls
)
142 (model
.source
, model
.decls
) = ('', {})
143 options
+= [lambda model
, options
: add_import(model
, options
, n
)]
146 def add_top_level_decl(model
, options
):
147 n
= model
.make_name()
148 d
= random
.choice([decl
for decl
in decls
if decl
.valid(model
)])
150 if not d
.valid(model
):
155 def add_import(model
, options
, module_name
):
157 if module_name
in model
.modules
:
158 model
.source
+= '#include "%s.h"\n' % module_name
159 model
.decls
.update(model
.modules
[module_name
][1])
162 sys
.stdout
.write('Finding bug: ')
166 sys
.stdout
.write('.')