@@ -14,7 +14,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
14
14
use rustc_middle:: middle:: dependency_format:: Linkage ;
15
15
use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
16
16
use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , MaybeResult , TyAndLayout } ;
17
- use rustc_middle:: ty:: { self , FloatTy , IntTy , Ty , TyCtxt , UintTy } ;
17
+ use rustc_middle:: ty:: { self , Binder , FloatTy , FnSig , IntTy , Ty , TyCtxt , UintTy } ;
18
18
use rustc_session:: config:: CrateType ;
19
19
use rustc_span:: { Span , Symbol } ;
20
20
use rustc_target:: callconv:: { Conv , FnAbi } ;
@@ -1187,6 +1187,58 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
1187
1187
1188
1188
interp_ok ( array)
1189
1189
}
1190
+
1191
+ fn check_fn_abi (
1192
+ & mut self ,
1193
+ input_args : & [ Ty < ' tcx > ] ,
1194
+ output_ty : Ty < ' tcx > ,
1195
+ safety : Safety ,
1196
+ abi : ExternAbi ,
1197
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1198
+ ) -> InterpResult < ' tcx , ( ) > {
1199
+ let this = self . eval_context_mut ( ) ;
1200
+ let mut inputs_and_output = input_args. to_vec ( ) ;
1201
+ inputs_and_output. push ( output_ty) ;
1202
+ let fn_sig_binder = Binder :: dummy ( FnSig {
1203
+ inputs_and_output : this. machine . tcx . mk_type_list ( & inputs_and_output) ,
1204
+ c_variadic : false ,
1205
+ safety,
1206
+ abi,
1207
+ } ) ;
1208
+ let exp_fn_abi = this. fn_abi_of_fn_ptr ( fn_sig_binder, Default :: default ( ) ) ?;
1209
+ if !self . check_abi_compat ( fn_abi, exp_fn_abi) ? {
1210
+ throw_ub_format ! ( "Invalid argument type: ABI mismatch" ) ;
1211
+ }
1212
+ interp_ok ( ( ) )
1213
+ }
1214
+
1215
+ // Check where two FnAbi's are compatible
1216
+ fn check_abi_compat (
1217
+ & mut self ,
1218
+ caller_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1219
+ callee_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1220
+ ) -> InterpResult < ' tcx , bool > {
1221
+ let this = self . eval_context_mut ( ) ;
1222
+ let caller_args_abi = & caller_fn_abi. args ;
1223
+ let callee_args_abi = & callee_fn_abi. args ;
1224
+
1225
+ if caller_fn_abi. c_variadic != callee_fn_abi. c_variadic
1226
+ || callee_fn_abi. fixed_count != caller_fn_abi. fixed_count
1227
+ || callee_fn_abi. can_unwind != caller_fn_abi. can_unwind
1228
+ || !this. check_argument_compat ( & caller_fn_abi. ret , & callee_fn_abi. ret ) ?
1229
+ || !caller_args_abi
1230
+ . iter ( )
1231
+ . zip ( callee_args_abi. iter ( ) )
1232
+ . map ( |( caller_arg, callee_arg) | this. check_argument_compat ( caller_arg, callee_arg) )
1233
+ . collect :: < InterpResult < ' tcx , Vec < bool > > > ( ) ?
1234
+ . into_iter ( )
1235
+ . all ( |b| b)
1236
+ {
1237
+ return interp_ok ( false ) ;
1238
+ }
1239
+
1240
+ interp_ok ( true )
1241
+ }
1190
1242
}
1191
1243
1192
1244
impl < ' tcx > MiriMachine < ' tcx > {
0 commit comments