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
18 def __init__(self
, text
, depends
=[], provides
=[], conflicts
=[]):
20 self
.depends
= depends
21 self
.provides
= provides
22 self
.conflicts
= conflicts
24 def valid(self
, model
):
25 for i
in self
.depends
:
26 if i
not in model
.decls
:
28 for i
in self
.conflicts
:
33 def apply(self
, model
, name
):
34 for i
in self
.provides
:
36 model
.source
+= self
.text
% {"name": name
}
40 Decl("struct X { int n; };\n", provides
=["X"], conflicts
=["X"]),
41 Decl('static_assert(X{.n=1}.n == 1, "");\n', depends
=["X"]),
42 Decl("X %(name)s;\n", depends
=["X"]),
51 def write(self
, path
, contents
):
52 self
.fs
[path
] = contents
55 for f
, s
in self
.fs
.items():
56 if self
.prevfs
.get(f
) != s
:
65 self
.prevfs
, self
.fs
= self
.fs
, {}
71 class CodeModel(object):
80 return "n" + str(self
.i
)
86 'module %s { header "%s.h" export * }\n' % (m
, m
)
87 for m
in self
.modules
.keys()
91 for m
, (s
, _
) in self
.modules
.items():
92 fs
.write("%s.h" % m
, s
)
94 fs
.write("main.cc", self
.source
)
99 [clang
, "-std=c++11", "-c", "-fmodules", "main.cc", "-o", "/dev/null"]
110 for d
in mutations(model
):
113 if not model
.fails():
115 except KeyboardInterrupt:
119 sys
.stdout
.write("\nReducing:\n")
124 assert m
, "got a failure with no steps; broken clang binary?"
125 i
= random
.choice(list(range(len(m
))))
126 x
= m
[0:i
] + m
[i
+ 1 :]
134 sys
.stdout
.write(".")
136 except KeyboardInterrupt:
137 # FIXME: Clean out output directory first.
144 i
= int(random
.uniform(0, len(options
) + none_opts
))
145 if i
>= len(options
):
150 def mutations(model
):
151 options
= [create_module
, add_top_level_decl
]
152 for opt
in choose(options
):
153 yield opt(model
, options
)
156 def create_module(model
, options
):
157 n
= model
.make_name()
160 model
.modules
[n
] = (model
.source
, model
.decls
)
161 (model
.source
, model
.decls
) = ("", {})
163 options
+= [lambda model
, options
: add_import(model
, options
, n
)]
167 def add_top_level_decl(model
, options
):
168 n
= model
.make_name()
169 d
= random
.choice([decl
for decl
in decls
if decl
.valid(model
)])
172 if not d
.valid(model
):
179 def add_import(model
, options
, module_name
):
181 if module_name
in model
.modules
:
182 model
.source
+= '#include "%s.h"\n' % module_name
183 model
.decls
.update(model
.modules
[module_name
][1])
188 sys
.stdout
.write("Finding bug: ")
192 sys
.stdout
.write(".")