Skip to content

Commit 91b4a0c

Browse files
committed
Add beginnings of a fuzzer to rustboot.
1 parent cd1a765 commit 91b4a0c

File tree

4 files changed

+178
-1
lines changed

4 files changed

+178
-1
lines changed

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ ME_MLS := $(addprefix boot/me/, walk.ml semant.ml resolve.ml alias.ml \
236236
type.ml dead.ml effect.ml typestate.ml loop.ml layout.ml \
237237
transutil.ml trans.ml dwarf.ml)
238238
FE_MLS := $(addprefix boot/fe/, ast.ml token.ml lexer.ml parser.ml pexp.ml \
239-
item.ml cexp.ml)
239+
item.ml cexp.ml fuzz.ml)
240240
DRIVER_TOP_MLS := $(addprefix boot/driver/, lib.ml $(VARIANT)/glue.ml main.ml)
241241

242242
BOOT_MLS := $(UTIL_BOT_MLS) $(DRIVER_BOT_MLS) $(FE_MLS) $(IL_MLS) $(ME_MLS) \

src/boot/driver/main.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ let (sess:Session.sess) =
6060
Session.sess_report_gc = false;
6161
Session.sess_report_deps = false;
6262
Session.sess_next_crate_id = 0;
63+
Session.sess_fuzz_item_count = 5;
6364
Session.sess_timings = Hashtbl.create 0;
6465
Session.sess_lib_dirs = Queue.create ();
6566
Session.sess_crate_meta = Hashtbl.create 0;
@@ -219,6 +220,15 @@ let argspecs =
219220
(flag (fun _ -> sess.Session.sess_use_pexps <- true)
220221
"-pexp" "use pexp portion of AST");
221222

223+
("-zc", Arg.Int (fun i -> sess.Session.sess_fuzz_item_count <- i),
224+
"count of items to generate when fuzzing");
225+
226+
("-zs", Arg.Int (fun i -> Fuzz.fuzz (Some i) sess),
227+
"run fuzzer with given seed");
228+
229+
(flag (fun _ -> Fuzz.fuzz None sess)
230+
"-z" "run fuzzer with random seed")
231+
222232
] @ (Glue.alt_argspecs sess)
223233
;;
224234

src/boot/driver/session.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type sess =
4545
mutable sess_report_gc: bool;
4646
mutable sess_report_deps: bool;
4747
mutable sess_next_crate_id: int;
48+
mutable sess_fuzz_item_count: int;
4849
sess_timings: (string, float) Hashtbl.t;
4950
sess_spans: (node_id,span) Hashtbl.t;
5051
sess_lib_dirs: filename Queue.t;

src/boot/fe/fuzz.ml

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
open Common;;
2+
open Ast;;
3+
4+
let ident_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";;
5+
let digit_chars = "1234567890";;
6+
7+
type scope =
8+
SCOPE_crate of crate
9+
| SCOPE_mod_item of (ident * mod_item)
10+
| SCOPE_block of block
11+
| SCOPE_anon
12+
;;
13+
14+
type ctxt =
15+
{
16+
ctxt_scopes: scope Stack.t;
17+
ctxt_node_counter: int ref;
18+
ctxt_sess: Session.sess;
19+
}
20+
21+
let generate_ident _ : ident =
22+
let char n =
23+
if n = 0
24+
then '_'
25+
else ident_chars.[Random.int (String.length ident_chars)]
26+
in
27+
let i = 3 + (Random.int 10) in
28+
let s = String.create i in
29+
for j = 0 to (i-1)
30+
do
31+
s.[j] <- char j
32+
done;
33+
s
34+
;;
35+
36+
let wrap (n:'a) (cx:ctxt) : 'a identified =
37+
incr cx.ctxt_node_counter;
38+
{ node = n; id = Node (!(cx.ctxt_node_counter)) }
39+
;;
40+
41+
let generate_in (scope:scope) (fn:(ctxt -> 'a)) (cx:ctxt) : 'a =
42+
Stack.push scope cx.ctxt_scopes;
43+
let x = fn cx in
44+
ignore (Stack.pop cx.ctxt_scopes);
45+
x
46+
;;
47+
48+
let generate_some (fn:(ctxt -> 'a)) (cx:ctxt) : 'a array =
49+
let root_count = cx.ctxt_sess.Session.sess_fuzz_item_count in
50+
let depth = Stack.length cx.ctxt_scopes in
51+
if depth >= root_count
52+
then [| |]
53+
else
54+
Array.init (1 + (Random.int (root_count - depth)))
55+
(fun _ -> fn cx)
56+
;;
57+
58+
let rec generate_ty (cx:ctxt) : ty =
59+
let subty _ =
60+
generate_in SCOPE_anon
61+
generate_ty cx
62+
in
63+
match Random.int (if Random.bool() then 10 else 17) with
64+
0 -> TY_nil
65+
| 1 -> TY_bool
66+
67+
| 2 -> TY_mach TY_u8
68+
| 3 -> TY_mach TY_u32
69+
70+
| 4 -> TY_mach TY_i8
71+
| 5 -> TY_mach TY_i32
72+
73+
| 6 -> TY_int
74+
| 7 -> TY_uint
75+
| 8 -> TY_char
76+
| 9 -> TY_str
77+
78+
| 10 -> TY_tup (generate_in SCOPE_anon
79+
(generate_some
80+
generate_ty) cx)
81+
| 11 -> TY_vec (subty())
82+
| 12 ->
83+
let generate_elt cx =
84+
(generate_ident cx, generate_ty cx)
85+
in
86+
TY_rec (generate_in SCOPE_anon
87+
(generate_some generate_elt) cx)
88+
89+
| 13 -> TY_chan (subty())
90+
| 14 -> TY_port (subty())
91+
92+
| 15 -> TY_task
93+
94+
| _ -> TY_box (subty())
95+
;;
96+
97+
98+
let rec generate_mod_item (mis:mod_items) (cx:ctxt) : unit =
99+
let ident = generate_ident () in
100+
let decl i = wrap { decl_item = i;
101+
decl_params = [| |] } cx
102+
in
103+
let item =
104+
match Random.int 2 with
105+
0 ->
106+
let ty = generate_ty cx in
107+
let eff = PURE in
108+
decl (MOD_ITEM_type (eff, ty))
109+
| _ ->
110+
let mis' = Hashtbl.create 0 in
111+
let view = { view_imports = Hashtbl.create 0;
112+
view_exports = Hashtbl.create 0; }
113+
in
114+
let item =
115+
decl (MOD_ITEM_mod (view, mis'))
116+
in
117+
let scope =
118+
SCOPE_mod_item (ident, item)
119+
in
120+
ignore
121+
(generate_in scope
122+
(generate_some (generate_mod_item mis'))
123+
cx);
124+
item
125+
in
126+
Hashtbl.add mis ident item
127+
;;
128+
129+
let fuzz (seed:int option) (sess:Session.sess) : unit =
130+
begin
131+
match seed with
132+
None -> Random.self_init ()
133+
| Some s -> Random.init s
134+
end;
135+
let filename =
136+
match sess.Session.sess_out with
137+
Some o -> o
138+
| None ->
139+
match seed with
140+
None -> "fuzz.rs"
141+
| Some seed -> "fuzz-" ^ (string_of_int seed) ^ ".rs"
142+
in
143+
let out = open_out_bin filename in
144+
let ff = Format.formatter_of_out_channel out in
145+
let cx = { ctxt_scopes = Stack.create ();
146+
ctxt_node_counter = ref 0;
147+
ctxt_sess = sess }
148+
in
149+
let mis = Hashtbl.create 0 in
150+
ignore (generate_some
151+
(generate_mod_item mis) cx);
152+
fmt_mod_items ff mis;
153+
Format.pp_print_flush ff ();
154+
close_out out;
155+
exit 0
156+
;;
157+
158+
159+
(*
160+
* Local Variables:
161+
* fill-column: 78;
162+
* indent-tabs-mode: nil
163+
* buffer-file-coding-system: utf-8-unix
164+
* compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
165+
* End:
166+
*)

0 commit comments

Comments
 (0)