|
16 | 16 | /// For the current CBMC implementation of function restrictions, see:
|
17 | 17 | /// http://cprover.diffblue.com/md__home_travis_build_diffblue_cbmc_doc_architectural_restrict-function-pointer.html
|
18 | 18 | use crate::GotocCtx;
|
19 |
| -use cbmc::goto_program::{Expr, Location, Stmt, Symbol, Type}; |
| 19 | +use cbmc::goto_program::{Stmt, Type}; |
20 | 20 | use cbmc::InternedString;
|
21 |
| -use cbmc::NO_PRETTY_NAME; |
22 | 21 | use kani_restrictions::{CallSite, PossibleMethodEntry, TraitDefinedMethod, VtableCtxResults};
|
23 | 22 | use rustc_data_structures::stable_map::FxHashMap;
|
24 | 23 | use tracing::debug;
|
@@ -92,98 +91,44 @@ impl VtableCtx {
|
92 | 91 | trait_name: InternedString,
|
93 | 92 | method: usize,
|
94 | 93 | function_name: InternedString,
|
| 94 | + label: InternedString, |
95 | 95 | ) {
|
96 | 96 | assert!(self.emit_vtable_restrictions);
|
97 | 97 | let site = CallSite {
|
98 | 98 | trait_method: TraitDefinedMethod { trait_name, vtable_idx: method },
|
99 | 99 | function_name: function_name,
|
| 100 | + label: label, |
100 | 101 | };
|
101 | 102 | self.call_sites.push(site);
|
102 | 103 | }
|
103 | 104 | }
|
104 | 105 |
|
105 | 106 | impl<'tcx> GotocCtx<'tcx> {
|
106 |
| - /// Wrap a virtual call through a function pointer and restrict the |
107 |
| - /// possible targets. |
108 |
| - /// |
109 |
| - /// We need to wrap because for the current implemention, CBMC employs |
110 |
| - /// a hard-to-get-right naming scheme for restrictions: the call site is |
111 |
| - /// named for its index in a given function. We don't have a good way to |
112 |
| - /// track _all_ function pointers within the function, so wrapping the call |
113 |
| - /// to a function that makes a single virtual function pointer call makes |
114 |
| - /// the naming unambiguous. |
115 |
| - /// |
116 |
| - /// This can be simplified if CBMC implemented label-based restrictions. |
117 |
| - /// Kani tracking: https://github.com/model-checking/kani/issues/651 |
118 |
| - /// CBMC tracking: https://github.com/diffblue/cbmc/issues/6464 |
| 107 | + /// Create a label to the virtual call site |
119 | 108 | pub fn virtual_call_with_restricted_fn_ptr(
|
120 | 109 | &mut self,
|
121 | 110 | trait_ty: Type,
|
122 | 111 | vtable_idx: usize,
|
123 |
| - fn_ptr: Expr, |
124 |
| - args: Vec<Expr>, |
125 |
| - ) -> Expr { |
| 112 | + body: Stmt, |
| 113 | + ) -> Stmt { |
126 | 114 | assert!(self.vtable_ctx.emit_vtable_restrictions);
|
127 | 115 |
|
128 |
| - // Crate-based naming scheme for wrappers |
129 |
| - let full_crate_name = self.full_crate_name().to_string().replace("::", "_"); |
130 |
| - let wrapper_name: InternedString = format!( |
131 |
| - "restricted_call_{}_{}", |
132 |
| - full_crate_name, |
133 |
| - self.vtable_ctx.get_call_site_global_idx() |
134 |
| - ) |
135 |
| - .into(); |
| 116 | + let label: InternedString = |
| 117 | + format!("restricted_call_label_{}", self.vtable_ctx.get_call_site_global_idx()).into(); |
136 | 118 |
|
137 | 119 | // We only have the Gotoc type, we need to normalize to match the MIR type.
|
138 | 120 | assert!(trait_ty.is_struct_tag());
|
139 | 121 | let mir_name =
|
140 | 122 | self.normalized_trait_name(*self.type_map.get(&trait_ty.tag().unwrap()).unwrap());
|
141 |
| - self.vtable_ctx.add_call_site(mir_name.into(), vtable_idx, wrapper_name); |
142 |
| - |
143 |
| - // Declare the wrapper's parameters |
144 |
| - let func_exp: Expr = fn_ptr.dereference(); |
145 |
| - let fn_type = func_exp.typ().clone(); |
146 |
| - let parameters: Vec<Symbol> = fn_type |
147 |
| - .parameters() |
148 |
| - .unwrap() |
149 |
| - .iter() |
150 |
| - .enumerate() |
151 |
| - .map(|(i, parameter)| { |
152 |
| - let name = format!("{}_{}", wrapper_name, i); |
153 |
| - let param = |
154 |
| - Symbol::variable(name.clone(), name, parameter.typ().clone(), Location::none()); |
155 |
| - self.symbol_table.insert(param.clone()); |
156 |
| - param |
157 |
| - }) |
158 |
| - .collect(); |
159 |
| - |
160 |
| - // Finish constructing the wrapper type |
161 |
| - let ret_typ = fn_type.return_type().unwrap().clone(); |
162 |
| - let param_typs = parameters.clone().iter().map(|p| p.to_function_parameter()).collect(); |
163 |
| - let new_typ = if fn_type.is_code() { |
164 |
| - Type::code(param_typs, ret_typ.clone()) |
165 |
| - } else if fn_type.is_variadic_code() { |
166 |
| - Type::variadic_code(param_typs, ret_typ.clone()) |
167 |
| - } else { |
168 |
| - unreachable!("Function type must be Code or VariadicCode") |
169 |
| - }; |
170 | 123 |
|
171 |
| - // Build the body: call the original function pointer |
172 |
| - let body = func_exp |
173 |
| - .clone() |
174 |
| - .call(parameters.iter().map(|p| p.to_expr()).collect()) |
175 |
| - .ret(Location::none()); |
176 |
| - |
177 |
| - // Build and insert the wrapper function itself |
178 |
| - let sym = Symbol::function( |
179 |
| - wrapper_name, |
180 |
| - new_typ, |
181 |
| - Some(Stmt::block(vec![body], Location::none())), |
182 |
| - NO_PRETTY_NAME, |
183 |
| - Location::none(), |
| 124 | + // Label |
| 125 | + self.vtable_ctx.add_call_site( |
| 126 | + mir_name.into(), |
| 127 | + vtable_idx, |
| 128 | + self.current_fn().name().into(), |
| 129 | + label, |
184 | 130 | );
|
185 |
| - self.symbol_table.insert(sym.clone()); |
186 |
| - sym.to_expr().call(args.to_vec()) |
| 131 | + body.with_label(label) |
187 | 132 | }
|
188 | 133 | }
|
189 | 134 |
|
|
0 commit comments