@@ -2,7 +2,12 @@ use super::{generator::generate_n_values, utils::did_need_in_closure_cause_panic
2
2
use crate :: {
3
3
compiler:: hir,
4
4
database:: Database ,
5
- vm:: { self , tracer:: Tracer , use_provider:: DbUseProvider , Closure , Heap , Pointer , Vm } ,
5
+ vm:: {
6
+ self ,
7
+ context:: { ExecutionController , UseProvider } ,
8
+ tracer:: Tracer ,
9
+ Closure , Heap , Pointer , TearDownResult , Vm ,
10
+ } ,
6
11
} ;
7
12
use std:: mem;
8
13
@@ -32,7 +37,7 @@ pub enum Status {
32
37
}
33
38
34
39
impl Status {
35
- fn new_fuzzing_attempt ( db : & Database , closure_heap : & Heap , closure : Pointer ) -> Status {
40
+ fn new_fuzzing_attempt ( closure_heap : & Heap , closure : Pointer ) -> Status {
36
41
let num_args = {
37
42
let closure: Closure = closure_heap. get ( closure) . data . clone ( ) . try_into ( ) . unwrap ( ) ;
38
43
closure. num_args
@@ -42,19 +47,19 @@ impl Status {
42
47
let closure = closure_heap. clone_single_to_other_heap ( & mut vm_heap, closure) ;
43
48
let arguments = generate_n_values ( & mut vm_heap, num_args) ;
44
49
45
- let use_provider = DbUseProvider { db } ;
46
- let vm = Vm :: new_for_running_closure ( vm_heap, & use_provider , closure, & arguments) ;
50
+ let mut vm = Vm :: new ( ) ;
51
+ vm . set_up_for_running_closure ( vm_heap, closure, & arguments) ;
47
52
48
53
Status :: StillFuzzing { vm, arguments }
49
54
}
50
55
}
51
56
impl Fuzzer {
52
- pub fn new ( db : & Database , closure_heap : & Heap , closure : Pointer , closure_id : hir:: Id ) -> Self {
57
+ pub fn new ( closure_heap : & Heap , closure : Pointer , closure_id : hir:: Id ) -> Self {
53
58
// The given `closure_heap` may contain other fuzzable closures.
54
59
let mut heap = Heap :: default ( ) ;
55
60
let closure = closure_heap. clone_single_to_other_heap ( & mut heap, closure) ;
56
61
57
- let status = Status :: new_fuzzing_attempt ( db , & heap, closure) ;
62
+ let status = Status :: new_fuzzing_attempt ( & heap, closure) ;
58
63
Self {
59
64
closure_heap : heap,
60
65
closure,
@@ -67,62 +72,53 @@ impl Fuzzer {
67
72
self . status . as_ref ( ) . unwrap ( )
68
73
}
69
74
70
- pub fn run ( & mut self , db : & Database , mut num_instructions : usize ) {
75
+ pub fn run < U : UseProvider , E : ExecutionController > (
76
+ & mut self ,
77
+ db : & Database ,
78
+ use_provider : & mut U ,
79
+ execution_controller : & mut E ,
80
+ ) {
71
81
let mut status = mem:: replace ( & mut self . status , None ) . unwrap ( ) ;
72
- while matches ! ( status, Status :: StillFuzzing { .. } ) {
73
- let ( new_status, num_instructions_executed) =
74
- self . map_status ( db, status, num_instructions) ;
75
- status = new_status;
76
-
77
- if num_instructions_executed >= num_instructions {
78
- break ;
79
- } else {
80
- num_instructions -= num_instructions_executed;
81
- }
82
+ while matches ! ( status, Status :: StillFuzzing { .. } )
83
+ && execution_controller. should_continue_running ( )
84
+ {
85
+ status = self . map_status ( status, db, use_provider, execution_controller) ;
82
86
}
83
87
self . status = Some ( status) ;
84
88
}
85
- fn map_status (
89
+ fn map_status < U : UseProvider , E : ExecutionController > (
86
90
& self ,
87
- db : & Database ,
88
91
status : Status ,
89
- num_instructions : usize ,
90
- ) -> ( Status , usize ) {
92
+ db : & Database ,
93
+ use_provider : & mut U ,
94
+ execution_controller : & mut E ,
95
+ ) -> Status {
91
96
match status {
92
- Status :: StillFuzzing { mut vm, arguments } => match & vm. status {
93
- vm:: Status :: Running => {
94
- let use_provider = DbUseProvider { db } ;
95
- let num_instructions_executed_before = vm. num_instructions_executed ;
96
- vm. run ( & use_provider, num_instructions) ;
97
- let num_instruction_executed =
98
- vm. num_instructions_executed - num_instructions_executed_before;
99
- (
100
- Status :: StillFuzzing { vm, arguments } ,
101
- num_instruction_executed,
102
- )
97
+ Status :: StillFuzzing { mut vm, arguments } => match vm. status ( ) {
98
+ vm:: Status :: CanRun => {
99
+ vm. run ( use_provider, execution_controller) ;
100
+ Status :: StillFuzzing { vm, arguments }
103
101
}
102
+ vm:: Status :: WaitingForOperations => panic ! ( "Fuzzing should not have to wait on channel operations because arguments were not channels." ) ,
104
103
// The VM finished running without panicking.
105
- vm:: Status :: Done => (
106
- Status :: new_fuzzing_attempt ( db, & self . closure_heap , self . closure ) ,
107
- 0 ,
108
- ) ,
104
+ vm:: Status :: Done => Status :: new_fuzzing_attempt ( & self . closure_heap , self . closure ) ,
109
105
vm:: Status :: Panicked { reason } => {
110
106
// If a `needs` directly inside the tested closure was not
111
107
// satisfied, then the panic is not closure's fault, but our
112
108
// fault.
109
+ let TearDownResult { heap, tracer, .. } = vm. tear_down ( ) ;
113
110
let is_our_fault =
114
- did_need_in_closure_cause_panic ( db, & self . closure_id , & vm . tracer ) ;
115
- let status = if is_our_fault {
116
- Status :: new_fuzzing_attempt ( db , & self . closure_heap , self . closure )
111
+ did_need_in_closure_cause_panic ( db, & self . closure_id , & tracer) ;
112
+ if is_our_fault {
113
+ Status :: new_fuzzing_attempt ( & self . closure_heap , self . closure )
117
114
} else {
118
115
Status :: PanickedForArguments {
119
- heap : vm . heap ,
116
+ heap,
120
117
arguments,
121
- reason : reason . clone ( ) ,
122
- tracer : vm . tracer . clone ( ) ,
118
+ reason,
119
+ tracer,
123
120
}
124
- } ;
125
- ( status, 0 )
121
+ }
126
122
}
127
123
} ,
128
124
// We already found some arguments that caused the closure to panic,
@@ -132,15 +128,12 @@ impl Fuzzer {
132
128
arguments,
133
129
reason,
134
130
tracer,
135
- } => (
136
- Status :: PanickedForArguments {
137
- heap,
138
- arguments,
139
- reason,
140
- tracer,
141
- } ,
142
- 0 ,
143
- ) ,
131
+ } => Status :: PanickedForArguments {
132
+ heap,
133
+ arguments,
134
+ reason,
135
+ tracer,
136
+ } ,
144
137
}
145
138
}
146
139
}
0 commit comments