1use rustc_abi::VariantIdx;
2use rustc_data_structures::graph;
3use rustc_hir::def_id::DefId;
4use rustc_middle::{
5 mir::{
6 AggregateKind, BasicBlock, BasicBlockData, Body, Local, Operand, Place, ProjectionElem,
7 Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
8 },
9 ty::{self, InstanceKind::Item, Ty, TyKind, TypeVisitable},
10};
11use rustc_span::{Symbol, source_map::Spanned};
12
13use annotate_snippets::{Level, Renderer, Snippet};
14use std::ops::Add;
15use z3::ast::{self, Ast};
16
17use super::super::{IcxMut, IcxSliceMut, Rcx, RcxMut};
18use super::is_z3_goal_verbose;
19use super::ownership::IntraVar;
20use super::{FlowAnalysis, IcxSliceFroBlock, IntraFlowAnalysis};
21use crate::{
22 analysis::core::ownedheap_analysis::{default::*, *},
23 utils::{
24 log::{
25 are_spans_in_same_file, relative_pos_range, span_to_filename, span_to_line_number,
26 span_to_source_code,
27 },
28 source::get_name,
29 },
30};
31
32type Disc = Option<VariantIdx>;
33type Aggre = Option<usize>;
34
35#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
36pub enum AsgnKind {
37 Assign,
38 Reference,
39 Pointer,
40 Cast,
41 Aggregate,
42}
43
44impl<'tcx, 'a> FlowAnalysis<'tcx, 'a> {
45 pub fn intra_run(&mut self) {
46 let tcx = self.tcx();
47 let mir_keys = tcx.mir_keys(());
48
49 for each_mir in mir_keys {
50 let def_id = each_mir.to_def_id();
51 let body = tcx.instance_mir(Item(def_id));
52 if graph::is_cyclic(&body.basic_blocks) {
53 continue;
54 }
55 if format!("{:?}", def_id).contains("syscall_dispatch") {
56 continue;
57 }
58
59 let mut cfg = z3::Config::new();
60 cfg.set_model_generation(true);
61 cfg.set_timeout_msec(1000);
62 let ctx = z3::Context::new(&cfg);
63 let goal = z3::Goal::new(&ctx, true, false, false);
64 let solver = z3::Solver::new(&ctx);
65
66 let mut intra_visitor = IntraFlowAnalysis::new(self.rcx, def_id);
67 intra_visitor.visit_body(&ctx, &goal, &solver, body);
68 }
69 }
70}
71
72impl<'tcx, 'ctx, 'a> IntraFlowAnalysis<'tcx, 'ctx, 'a> {
73 pub(crate) fn visit_body(
74 &mut self,
75 ctx: &'ctx z3::Context,
76 goal: &'ctx z3::Goal<'ctx>,
77 solver: &'ctx z3::Solver<'ctx>,
78 body: &'tcx Body<'tcx>,
79 ) {
80 let topo: Vec<usize> = self.graph.get_topo().iter().map(|id| *id).collect();
81 for bidx in topo {
82 let data = &body.basic_blocks[BasicBlock::from(bidx)];
83 self.visit_block_data(ctx, goal, solver, data, bidx);
84 }
85 }
86
87 pub(crate) fn visit_block_data(
88 &mut self,
89 ctx: &'ctx z3::Context,
90 goal: &'ctx z3::Goal<'ctx>,
91 solver: &'ctx z3::Solver<'ctx>,
92 data: &'tcx BasicBlockData<'tcx>,
93 bidx: usize,
94 ) {
95 self.preprocess_for_basic_block(ctx, goal, solver, bidx);
96
97 for (sidx, stmt) in data.statements.iter().enumerate() {
98 self.visit_statement(ctx, goal, solver, stmt, bidx, sidx);
99 }
100
101 self.visit_terminator(ctx, goal, solver, data.terminator(), bidx);
102
103 self.reprocess_for_basic_block(bidx);
104 }
105
106 pub(crate) fn preprocess_for_basic_block(
107 &mut self,
108 ctx: &'ctx z3::Context,
109 goal: &'ctx z3::Goal<'ctx>,
110 solver: &'ctx z3::Solver<'ctx>,
111 bidx: usize,
112 ) {
113 if bidx == 0 {
115 let mut icx_slice = IcxSliceFroBlock::new_for_block_0(self.body.local_decls.len());
116
117 for arg_idx in 0..self.body.arg_count {
118 let idx = arg_idx + 1;
119 let ty = self.body.local_decls[Local::from_usize(idx)].ty;
120
121 let ty_with_index = TyWithIndex::new(ty, None);
122 if ty_with_index == TyWithIndex(None) {
123 self.handle_intra_var_unsupported(idx);
124 continue;
125 }
126
127 let default_layout = self.extract_default_ty_layout(ty, None);
128 if !default_layout.is_owned() {
129 icx_slice.len_mut()[idx] = 0;
130 icx_slice.var_mut()[idx] = IntraVar::Unsupported;
131 icx_slice.ty_mut()[idx] = TyWithIndex(None);
132 continue;
133 }
134 let int = rustbv_to_int(&heap_layout_to_rustbv(default_layout.layout()));
135
136 let name = new_local_name(idx, 0, 0).add("_arg_init");
137 let len = default_layout.layout().len();
138
139 let new_bv = ast::BV::new_const(ctx, name, len as u32);
140 let init_const = ast::BV::from_u64(ctx, int, len as u32);
141
142 let constraint_init_arg = new_bv._eq(&init_const);
143
144 goal.assert(&constraint_init_arg);
145 solver.assert(&constraint_init_arg);
146
147 icx_slice.len_mut()[idx] = len;
148 icx_slice.var_mut()[idx] = IntraVar::Init(new_bv);
149 icx_slice.ty_mut()[idx] = ty_with_index;
150 }
151
152 *self.icx_slice_mut() = icx_slice.clone();
153
154 return;
155 }
156
157 let pre = &self.graph.pre[bidx];
158
159 if pre.len() > 1 {
160 let mut v_pre_collect: Vec<IcxSliceFroBlock> = Vec::default();
162 for idx in pre {
163 v_pre_collect.push(IcxSliceFroBlock::new_out(self.icx_mut(), *idx));
164 }
165
166 let mut ans_icx_slice = v_pre_collect[0].clone();
168 let var_len = v_pre_collect[0].len().len();
169
170 for var_idx in 0..var_len {
172 let mut using_for_and_bv: Option<ast::BV> = None;
175 let mut ty = TyWithIndex::default();
176 let mut len = 0;
177
178 let mut unsupported = false;
179 for idx in 0..v_pre_collect.len() {
181 let var = &v_pre_collect[idx].var()[var_idx];
183 if var.is_declared() {
184 continue;
185 }
186 if var.is_unsupported() {
187 unsupported = true;
188 ans_icx_slice.len_mut()[var_idx] = 0;
189 ans_icx_slice.var_mut()[var_idx] = IntraVar::Unsupported;
190 break;
191 }
192
193 let var_bv = var.extract();
195 if ty == TyWithIndex(None) {
196 ty = v_pre_collect[idx].ty()[var_idx].clone();
197 len = v_pre_collect[idx].len()[var_idx];
198
199 ans_icx_slice.ty_mut()[var_idx] = ty.clone();
200 ans_icx_slice.len_mut()[var_idx] = len;
201
202 using_for_and_bv = Some(var_bv.clone());
203 }
204
205 if ty != v_pre_collect[idx].ty()[var_idx] {
206 unsupported = true;
207 ans_icx_slice.len_mut()[var_idx] = 0;
208 ans_icx_slice.var_mut()[var_idx] = IntraVar::Unsupported;
209 break;
210 }
211
212 let bv_and = using_for_and_bv.unwrap().bvand(&var_bv);
214 using_for_and_bv = Some(bv_and);
215 ans_icx_slice.taint_merge(&v_pre_collect[idx], var_idx);
216 }
217
218 if unsupported || using_for_and_bv.is_none() {
219 *self.icx_slice_mut() = ans_icx_slice.clone();
220 continue;
221 }
222
223 let name = new_local_name(var_idx, bidx, 0).add("_phi");
224 let phi_bv = ast::BV::new_const(ctx, name, len as u32);
225 let constraint_phi = phi_bv._eq(&using_for_and_bv.unwrap());
226
227 goal.assert(&constraint_phi);
228 solver.assert(&constraint_phi);
229
230 ans_icx_slice.var_mut()[var_idx] = IntraVar::Init(phi_bv);
231
232 *self.icx_slice_mut() = ans_icx_slice.clone();
233 }
234 } else {
235 if pre.len() == 0 {
236 rap_error!("The pre node is empty, check the logic is safe to launch.");
237 }
238 self.icx_mut().derive_from_pre_node(pre[0], bidx);
239 self.icx_slice = IcxSliceFroBlock::new_in(self.icx_mut(), bidx);
240 }
241
242 }
244
245 pub(crate) fn reprocess_for_basic_block(&mut self, bidx: usize) {
246 let icx_slice = self.icx_slice().clone();
247 self.icx_slice = IcxSliceFroBlock::default();
248 self.icx_mut().derive_from_icx_slice(icx_slice, bidx);
249 }
250
251 pub(crate) fn visit_statement(
252 &mut self,
253 ctx: &'ctx z3::Context,
254 goal: &'ctx z3::Goal<'ctx>,
255 solver: &'ctx z3::Solver<'ctx>,
256 stmt: &Statement<'tcx>,
257 bidx: usize,
258 sidx: usize,
259 ) {
260 match &stmt.kind {
261 StatementKind::Assign(box (place, rvalue)) => {
262 help_debug_goal_stmt(ctx, goal, bidx, sidx);
263
264 let disc: Disc = None;
265
266 self.visit_assign(ctx, goal, solver, place, rvalue, disc, bidx, sidx);
292 rap_debug!(
293 "IcxSlice in Assign: {} {}: {:?}\n{:?}\n",
294 bidx,
295 sidx,
296 stmt.kind,
297 self.icx_slice()
298 );
299 }
300 StatementKind::StorageLive(_local) => {}
301 StatementKind::StorageDead(_local) => {}
302 _ => (),
303 }
304 }
305
306 pub(crate) fn visit_terminator(
307 &mut self,
308 ctx: &'ctx z3::Context,
309 goal: &'ctx z3::Goal<'ctx>,
310 solver: &'ctx z3::Solver<'ctx>,
311 term: &'tcx Terminator<'tcx>,
312 bidx: usize,
313 ) {
314 help_debug_goal_term(ctx, goal, bidx);
315
316 match &term.kind {
317 TerminatorKind::Drop { place, .. } => {
318 self.handle_drop(ctx, goal, solver, place, bidx, false);
319 }
320 TerminatorKind::Call {
321 func,
322 args,
323 destination,
324 ..
325 } => {
326 self.handle_call(
327 ctx,
328 goal,
329 solver,
330 term.clone(),
331 &func,
332 &args,
333 &destination,
334 bidx,
335 );
336 }
337 TerminatorKind::Return => {
338 self.handle_return(ctx, goal, solver, bidx);
339 }
340 _ => (),
341 }
342
343 rap_debug!(
344 "IcxSlice in Terminator: {}: {:?}\n{:?}\n",
345 bidx,
346 term.kind,
347 self.icx_slice()
348 );
349 }
350
351 pub(crate) fn visit_assign(
352 &mut self,
353 ctx: &'ctx z3::Context,
354 goal: &'ctx z3::Goal<'ctx>,
355 solver: &'ctx z3::Solver<'ctx>,
356 lplace: &Place<'tcx>,
357 rvalue: &Rvalue<'tcx>,
358 disc: Disc,
359 bidx: usize,
360 sidx: usize,
361 ) {
362 let lvalue_has_projection = has_projection(lplace);
363
364 match rvalue {
365 Rvalue::Use(op) => {
366 let kind = AsgnKind::Assign;
367 let aggre = None;
368 match op {
369 Operand::Copy(rplace) => {
370 let rvalue_has_projection = has_projection(rplace);
371 match (lvalue_has_projection, rvalue_has_projection) {
372 (true, true) => {
373 self.handle_copy_field_to_field(
374 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
375 sidx,
376 );
377 }
378 (true, false) => {
379 self.handle_copy_to_field(
380 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
381 sidx,
382 );
383 }
384 (false, true) => {
385 self.handle_copy_from_field(
386 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
387 );
388 }
389 (false, false) => {
390 self.handle_copy(
391 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
392 );
393 }
394 }
395 }
396 Operand::Move(rplace) => {
397 let rvalue_has_projection = has_projection(rplace);
398 match (lvalue_has_projection, rvalue_has_projection) {
399 (true, true) => {
400 self.handle_move_field_to_field(
401 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
402 sidx,
403 );
404 }
405 (true, false) => {
406 self.handle_move_to_field(
407 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
408 sidx,
409 );
410 }
411 (false, true) => {
412 self.handle_move_from_field(
413 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
414 );
415 }
416 (false, false) => {
417 self.handle_move(
418 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
419 );
420 }
421 }
422 }
423 _ => (),
424 }
425 }
426 Rvalue::Ref(.., rplace) => {
427 let kind = AsgnKind::Reference;
428 let aggre = None;
429 let rvalue_has_projection = has_projection(rplace);
430 match (lvalue_has_projection, rvalue_has_projection) {
431 (true, true) => {
432 self.handle_copy_field_to_field(
433 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx, sidx,
434 );
435 }
436 (true, false) => {
437 self.handle_copy_to_field(
438 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx, sidx,
439 );
440 }
441 (false, true) => {
442 self.handle_copy_from_field(
443 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
444 );
445 }
446 (false, false) => {
447 self.handle_copy(ctx, goal, solver, kind, lplace, rplace, bidx, sidx);
448 }
449 }
450 }
451 Rvalue::RawPtr(_, rplace) => {
452 let kind = AsgnKind::Reference;
453 let aggre = None;
454 let rvalue_has_projection = has_projection(rplace);
455 match (lvalue_has_projection, rvalue_has_projection) {
456 (true, true) => {
457 self.handle_copy_field_to_field(
458 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx, sidx,
459 );
460 }
461 (true, false) => {
462 self.handle_copy_to_field(
463 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx, sidx,
464 );
465 }
466 (false, true) => {
467 self.handle_copy_from_field(
468 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
469 );
470 }
471 (false, false) => {
472 self.handle_copy(ctx, goal, solver, kind, lplace, rplace, bidx, sidx);
473 }
474 }
475 }
476 Rvalue::Cast(_cast_kind, op, ..) => {
477 let kind = AsgnKind::Cast;
478 let aggre = None;
479 match op {
480 Operand::Copy(rplace) => {
481 let rvalue_has_projection = has_projection(rplace);
482 match (lvalue_has_projection, rvalue_has_projection) {
483 (true, true) => {
484 self.handle_copy_field_to_field(
485 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
486 sidx,
487 );
488 }
489 (true, false) => {
490 self.handle_copy_to_field(
491 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
492 sidx,
493 );
494 }
495 (false, true) => {
496 self.handle_copy_from_field(
497 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
498 );
499 }
500 (false, false) => {
501 self.handle_copy(
502 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
503 );
504 }
505 }
506 }
507 Operand::Move(rplace) => {
508 let rvalue_has_projection = has_projection(rplace);
509 match (lvalue_has_projection, rvalue_has_projection) {
510 (true, true) => {
511 self.handle_move_field_to_field(
512 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
513 sidx,
514 );
515 }
516 (true, false) => {
517 self.handle_move_to_field(
518 ctx, goal, solver, kind, lplace, rplace, disc, aggre, bidx,
519 sidx,
520 );
521 }
522 (false, true) => {
523 self.handle_move_from_field(
524 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
525 );
526 }
527 (false, false) => {
528 self.handle_move(
529 ctx, goal, solver, kind, lplace, rplace, bidx, sidx,
530 );
531 }
532 }
533 }
534 _ => (),
535 }
536 }
537 Rvalue::Aggregate(akind, operands) => {
538 if lvalue_has_projection {
539 return;
540 }
541 let kind = AsgnKind::Aggregate;
542 match **akind {
543 AggregateKind::Adt(did, vidx, ..) => {
544 self.handle_aggregate_init(
545 ctx, goal, solver, kind, lplace, did, vidx, disc, bidx, sidx,
546 );
547 for (fidx, op) in operands.iter().enumerate() {
548 let aggre = Some(fidx);
549 match op {
550 Operand::Copy(rplace) => {
551 let rvalue_has_projection = has_projection(rplace);
552 match rvalue_has_projection {
553 true => {
554 self.handle_copy_field_to_field(
555 ctx, goal, solver, kind, lplace, rplace, disc,
556 aggre, bidx, sidx,
557 );
558 }
559 false => {
560 self.handle_copy_to_field(
561 ctx, goal, solver, kind, lplace, rplace, disc,
562 aggre, bidx, sidx,
563 );
564 }
565 }
566 }
567 Operand::Move(rplace) => {
568 let rvalue_has_projection = has_projection(rplace);
569 match rvalue_has_projection {
570 true => {
571 self.handle_move_field_to_field(
572 ctx, goal, solver, kind, lplace, rplace, disc,
573 aggre, bidx, sidx,
574 );
575 }
576 false => {
577 self.handle_move_to_field(
578 ctx, goal, solver, kind, lplace, rplace, disc,
579 aggre, bidx, sidx,
580 );
581 }
582 }
583 }
584 _ => (),
585 }
586 }
587 }
588 _ => {
589 return;
590 }
591 }
592 }
593 _ => (),
594 }
595 }
596
597 pub(crate) fn handle_copy(
598 &mut self,
599 ctx: &'ctx z3::Context,
600 goal: &'ctx z3::Goal<'ctx>,
601 solver: &'ctx z3::Solver<'ctx>,
602 _kind: AsgnKind,
603 lplace: &Place<'tcx>,
604 rplace: &Place<'tcx>,
605 bidx: usize,
606 sidx: usize,
607 ) {
608 let llocal = lplace.local;
609 let rlocal = rplace.local;
610
611 let lu: usize = llocal.as_usize();
612 let ru: usize = rlocal.as_usize();
613
614 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
616 {
617 self.handle_intra_var_unsupported(lu);
618 self.handle_intra_var_unsupported(ru);
619 return;
620 }
621 if !self.icx_slice().var[ru].is_init() {
622 return;
623 }
624
625 if self.icx_slice().len()[ru] == 0 {
628 return;
630 }
631
632 let mut llen = self.icx_slice().len()[lu];
634 let rlen = self.icx_slice().len()[ru];
635
636 let l_ori_bv: ast::BV;
638 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
639
640 let mut is_ctor = true;
641 if self.icx_slice().var()[lu].is_init() {
642 if self.icx_slice().ty()[lu] != self.icx_slice().ty[ru] {
647 self.handle_intra_var_unsupported(lu);
648 self.handle_intra_var_unsupported(ru);
649 return;
650 }
651 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
652 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
653 let constraint_l_ori_zero = l_ori_bv._safe_eq(&l_zero_const).unwrap();
654 goal.assert(&constraint_l_ori_zero);
655 solver.assert(&constraint_l_ori_zero);
656 is_ctor = false;
657 } else {
658 let r_place_ty = rplace.ty(&self.body.local_decls, self.tcx());
660 let ty_with_vidx = TyWithIndex::new(r_place_ty.ty, r_place_ty.variant_index);
661 match ty_with_vidx.get_priority() {
662 0 => {
663 self.handle_intra_var_unsupported(lu);
665 self.handle_intra_var_unsupported(ru);
666 return;
667 }
668 1 => {
669 return;
670 }
671 2 => {
672 self.icx_slice_mut().ty_mut()[lu] = self.icx_slice().ty()[ru].clone();
674 self.icx_slice_mut().layout_mut()[lu] = self.icx_slice().layout()[ru].clone();
675 }
676 _ => unreachable!(),
677 }
678 }
679
680 llen = rlen;
682 self.icx_slice_mut().len_mut()[lu] = llen;
683
684 let l_name = if is_ctor {
686 new_local_name(lu, bidx, sidx).add("_ctor_asgn")
687 } else {
688 new_local_name(lu, bidx, sidx)
689 };
690 let r_name = new_local_name(ru, bidx, sidx);
691
692 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
694 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
695
696 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
697 let r_zero_const = ast::BV::from_u64(ctx, 0, rlen as u32);
698
699 let r_owning = r_new_bv._safe_eq(&r_ori_bv).unwrap();
703 let l_non_owning = l_new_bv._safe_eq(&l_zero_const).unwrap();
704 let args1 = &[&r_owning, &l_non_owning];
705 let summary_1 = ast::Bool::and(ctx, args1);
706
707 let l_owning = l_new_bv._safe_eq(&r_ori_bv).unwrap();
709 let r_non_owning = r_new_bv._safe_eq(&r_zero_const).unwrap();
710 let args2 = &[&l_owning, &r_non_owning];
711 let summary_2 = ast::Bool::and(ctx, args2);
712
713 let args3 = &[&summary_1, &summary_2];
715 let constraint_owning_now = ast::Bool::or(ctx, args3);
716
717 goal.assert(&constraint_owning_now);
718 solver.assert(&constraint_owning_now);
719
720 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
722 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
723 self.handle_taint(lu, ru);
724 }
725
726 pub(crate) fn handle_move(
727 &mut self,
728 ctx: &'ctx z3::Context,
729 goal: &'ctx z3::Goal<'ctx>,
730 solver: &'ctx z3::Solver<'ctx>,
731 _kind: AsgnKind,
732 lplace: &Place<'tcx>,
733 rplace: &Place<'tcx>,
734 bidx: usize,
735 sidx: usize,
736 ) {
737 let llocal = lplace.local;
738 let rlocal = rplace.local;
739
740 let lu: usize = llocal.as_usize();
741 let ru: usize = rlocal.as_usize();
742
743 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
745 {
746 self.handle_intra_var_unsupported(lu);
747 self.handle_intra_var_unsupported(ru);
748 return;
749 }
750 if !self.icx_slice.var()[ru].is_init() {
751 return;
752 }
753
754 if self.icx_slice().len()[ru] == 0 {
757 return;
759 }
760
761 let mut llen = self.icx_slice().len()[lu];
763 let rlen = self.icx_slice().len()[ru];
764
765 let l_ori_bv: ast::BV;
767 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
768
769 let mut is_ctor = true;
770 if self.icx_slice().var()[lu].is_init() {
771 if self.icx_slice().ty()[lu] != self.icx_slice().ty[ru] {
776 self.handle_intra_var_unsupported(lu);
777 self.handle_intra_var_unsupported(ru);
778 return;
779 }
780 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
781 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
782 let constraint_l_ori_zero = l_ori_bv._safe_eq(&l_zero_const).unwrap();
783 goal.assert(&constraint_l_ori_zero);
784 solver.assert(&constraint_l_ori_zero);
785 is_ctor = false;
786 } else {
787 let r_place_ty = rplace.ty(&self.body.local_decls, self.tcx());
789 let ty_with_vidx = TyWithIndex::new(r_place_ty.ty, r_place_ty.variant_index);
790 match ty_with_vidx.get_priority() {
791 0 => {
792 self.handle_intra_var_unsupported(lu);
794 self.handle_intra_var_unsupported(ru);
795 return;
796 }
797 1 => {
798 return;
799 }
800 2 => {
801 self.icx_slice_mut().ty_mut()[lu] = self.icx_slice().ty()[ru].clone();
803 self.icx_slice_mut().layout_mut()[lu] = self.icx_slice().layout()[ru].clone();
804 }
805 _ => unreachable!(),
806 }
807 }
808
809 llen = rlen;
811 self.icx_slice_mut().len_mut()[lu] = llen;
812
813 let l_name = if is_ctor {
815 new_local_name(lu, bidx, sidx).add("_ctor_asgn")
816 } else {
817 new_local_name(lu, bidx, sidx)
818 };
819 let r_name = new_local_name(ru, bidx, sidx);
820
821 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
823 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
824
825 let r_zero_const = ast::BV::from_u64(ctx, 0, rlen as u32);
826
827 let r_non_owning = r_new_bv._safe_eq(&r_zero_const).unwrap();
831 let l_owning = l_new_bv._safe_eq(&r_ori_bv).unwrap();
833
834 goal.assert(&r_non_owning);
835 goal.assert(&l_owning);
836 solver.assert(&r_non_owning);
837 solver.assert(&l_owning);
838
839 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
841 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
842 self.handle_taint(lu, ru);
843 }
844
845 pub(crate) fn handle_copy_from_field(
846 &mut self,
847 ctx: &'ctx z3::Context,
848 goal: &'ctx z3::Goal<'ctx>,
849 solver: &'ctx z3::Solver<'ctx>,
850 _kind: AsgnKind,
851 lplace: &Place<'tcx>,
852 rplace: &Place<'tcx>,
853 bidx: usize,
854 sidx: usize,
855 ) {
856 let llocal = lplace.local;
859 let rlocal = rplace.local;
860
861 let lu: usize = llocal.as_usize();
862 let ru: usize = rlocal.as_usize();
863
864 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
866 {
867 self.handle_intra_var_unsupported(lu);
868 self.handle_intra_var_unsupported(ru);
869 return;
870 }
871 if !self.icx_slice().var()[ru].is_init() {
872 return;
873 }
874
875 if self.icx_slice().len[ru] == 0 {
878 return;
880 }
881
882 let rpj_ty = rplace.ty(&self.body.local_decls, self.tcx());
885 let rpj_fields = self.extract_projection(rplace, None);
886 if rpj_fields.is_unsupported() {
887 self.handle_intra_var_unsupported(lu);
889 self.handle_intra_var_unsupported(ru);
890 return;
891 }
892 if !rpj_fields.has_field() {
893 self.handle_copy(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
894 return;
895 }
896 let index_needed = rpj_fields.index_needed();
897
898 let default_heap = self.extract_default_ty_layout(rpj_ty.ty, rpj_ty.variant_index);
899 if !default_heap.get_requirement() || default_heap.is_empty() {
900 return;
901 }
902
903 let mut llen = self.icx_slice().len()[lu];
905 let rlen = self.icx_slice().len()[ru];
906 let rpj_len = default_heap.layout().len();
907
908 let l_ori_bv: ast::BV;
910 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
911
912 let mut is_ctor = true;
913 if self.icx_slice().var()[lu].is_init() {
914 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
918 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
919 let constraint_l_ori_zero = l_ori_bv._safe_eq(&l_zero_const).unwrap();
920 goal.assert(&constraint_l_ori_zero);
921 solver.assert(&constraint_l_ori_zero);
922 is_ctor = false;
923 } else {
924 let r_place_ty = rplace.ty(&self.body.local_decls, self.tcx());
927 let ty_with_vidx = TyWithIndex::new(r_place_ty.ty, r_place_ty.variant_index);
928 match ty_with_vidx.get_priority() {
929 0 => {
930 self.handle_intra_var_unsupported(lu);
932 self.handle_intra_var_unsupported(ru);
933 return;
934 }
935 1 => {
936 return;
937 }
938 2 => {
939 self.icx_slice_mut().ty_mut()[lu] = ty_with_vidx;
941 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout().clone();
942 }
943 _ => unreachable!(),
944 }
945 }
946
947 llen = rpj_len;
949 self.icx_slice_mut().len_mut()[lu] = llen;
950
951 let l_name = if is_ctor {
953 new_local_name(lu, bidx, sidx).add("_ctor_asgn")
954 } else {
955 new_local_name(lu, bidx, sidx)
956 };
957 let r_name = new_local_name(ru, bidx, sidx);
958
959 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
961 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
962
963 let r_f_owning = r_new_bv._safe_eq(&r_ori_bv).unwrap();
967 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
968 let l_non_owning = l_new_bv._safe_eq(&l_zero_const).unwrap();
969 let args1 = &[&r_f_owning, &l_non_owning];
970 let summary_1 = ast::Bool::and(ctx, args1);
971
972 let rust_bv_for_op_and = if self.icx_slice().taint()[ru].is_tainted() {
977 rustbv_merge(
978 &heap_layout_to_rustbv(default_heap.layout()),
979 &self.generate_ptr_layout(rpj_ty.ty, rpj_ty.variant_index),
980 )
981 } else {
982 heap_layout_to_rustbv(default_heap.layout())
983 };
984 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
985 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, llen as u32);
986 let extract_from_field = r_ori_bv.extract(index_needed as u32, index_needed as u32);
987 let repeat_field = if llen > 1 {
988 extract_from_field.sign_ext((llen - 1) as u32)
989 } else {
990 extract_from_field
991 };
992 let after_op_and = z3_bv_for_op_and.bvand(&repeat_field);
993 let l_extend_owning = l_new_bv._safe_eq(&after_op_and).unwrap();
994 let mut rust_bv_for_op_and = vec![true; rlen];
998 rust_bv_for_op_and[index_needed] = false;
999 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1000 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, rlen as u32);
1001 let after_op_and = r_ori_bv.bvand(&z3_bv_for_op_and);
1002 let rpj_non_owning = r_new_bv._safe_eq(&after_op_and).unwrap();
1003
1004 let args2 = &[&l_extend_owning, &rpj_non_owning];
1005 let summary_2 = ast::Bool::and(ctx, args2);
1006
1007 let args3 = &[&summary_1, &summary_2];
1009 let constraint_owning_now = ast::Bool::or(ctx, args3);
1010
1011 goal.assert(&constraint_owning_now);
1012 solver.assert(&constraint_owning_now);
1013
1014 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1016 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1017 self.handle_taint(lu, ru);
1018 }
1019
1020 pub(crate) fn handle_move_from_field(
1021 &mut self,
1022 ctx: &'ctx z3::Context,
1023 goal: &'ctx z3::Goal<'ctx>,
1024 solver: &'ctx z3::Solver<'ctx>,
1025 _kind: AsgnKind,
1026 lplace: &Place<'tcx>,
1027 rplace: &Place<'tcx>,
1028 bidx: usize,
1029 sidx: usize,
1030 ) {
1031 let llocal = lplace.local;
1034 let rlocal = rplace.local;
1035
1036 let lu: usize = llocal.as_usize();
1037 let ru: usize = rlocal.as_usize();
1038
1039 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
1041 {
1042 self.handle_intra_var_unsupported(lu);
1043 self.handle_intra_var_unsupported(ru);
1044 return;
1045 }
1046 if !self.icx_slice().var()[ru].is_init() {
1047 return;
1048 }
1049
1050 let rpj_ty = rplace.ty(&self.body.local_decls, self.tcx());
1053 let rpj_fields = self.extract_projection(rplace, None);
1054 if rpj_fields.is_unsupported() {
1055 self.handle_intra_var_unsupported(lu);
1057 self.handle_intra_var_unsupported(ru);
1058 return;
1059 }
1060 if !rpj_fields.has_field() {
1061 self.handle_move(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1062 return;
1063 }
1064 let index_needed = rpj_fields.index_needed();
1065
1066 let default_heap = self.extract_default_ty_layout(rpj_ty.ty, rpj_ty.variant_index);
1067 if !default_heap.get_requirement() || default_heap.is_empty() {
1068 return;
1069 }
1070
1071 let mut llen = self.icx_slice().len()[lu];
1073 let rlen = self.icx_slice().len()[ru];
1074 let rpj_len = default_heap.layout().len();
1075
1076 if self.icx_slice().len[ru] == 0 {
1079 return;
1081 }
1082
1083 let l_ori_bv: ast::BV;
1085 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
1086
1087 let mut is_ctor = true;
1088 if self.icx_slice().var()[lu].is_init() {
1089 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
1099 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
1100 let constraint_l_ori_zero = l_ori_bv._safe_eq(&l_zero_const).unwrap();
1101 goal.assert(&constraint_l_ori_zero);
1102 solver.assert(&constraint_l_ori_zero);
1103 is_ctor = false;
1104 } else {
1105 let r_place_ty = rplace.ty(&self.body.local_decls, self.tcx());
1108 let ty_with_vidx = TyWithIndex::new(r_place_ty.ty, r_place_ty.variant_index);
1109 match ty_with_vidx.get_priority() {
1110 0 => {
1111 self.handle_intra_var_unsupported(lu);
1113 self.handle_intra_var_unsupported(ru);
1114 return;
1115 }
1116 1 => {
1117 return;
1118 }
1119 2 => {
1120 self.icx_slice_mut().ty_mut()[lu] = ty_with_vidx;
1122 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout().clone();
1123 }
1124 _ => unreachable!(),
1125 }
1126 }
1127
1128 llen = rpj_len;
1130 self.icx_slice_mut().len_mut()[lu] = llen;
1131
1132 let l_name = if is_ctor {
1134 new_local_name(lu, bidx, sidx).add("_ctor_asgn")
1135 } else {
1136 new_local_name(lu, bidx, sidx)
1137 };
1138 let r_name = new_local_name(ru, bidx, sidx);
1139
1140 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
1142 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
1143
1144 let rust_bv_for_op_and = if self.icx_slice().taint()[ru].is_tainted() {
1150 rustbv_merge(
1151 &heap_layout_to_rustbv(default_heap.layout()),
1152 &self.generate_ptr_layout(rpj_ty.ty, rpj_ty.variant_index),
1153 )
1154 } else {
1155 heap_layout_to_rustbv(default_heap.layout())
1156 };
1157 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1158 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, llen as u32);
1159 let extract_from_field = r_ori_bv.extract(index_needed as u32, index_needed as u32);
1160 let repeat_field = if llen > 1 {
1161 extract_from_field.sign_ext((llen - 1) as u32)
1162 } else {
1163 extract_from_field
1164 };
1165 let after_op_and = z3_bv_for_op_and.bvand(&repeat_field);
1166 let l_extend_owning = l_new_bv._safe_eq(&after_op_and).unwrap();
1167
1168 let mut rust_bv_for_op_and = vec![true; rlen];
1172 rust_bv_for_op_and[index_needed] = false;
1173 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1174 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, rlen as u32);
1175 let after_op_and = r_ori_bv.bvand(&z3_bv_for_op_and);
1176 let rpj_non_owning = r_new_bv._safe_eq(&after_op_and).unwrap();
1177
1178 goal.assert(&l_extend_owning);
1179 goal.assert(&rpj_non_owning);
1180 solver.assert(&l_extend_owning);
1181 solver.assert(&rpj_non_owning);
1182
1183 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1185 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1186 self.handle_taint(lu, ru);
1187 }
1188 pub(crate) fn handle_aggregate_init(
1189 &mut self,
1190 ctx: &'ctx z3::Context,
1191 goal: &'ctx z3::Goal<'ctx>,
1192 solver: &'ctx z3::Solver<'ctx>,
1193 _kind: AsgnKind,
1194 lplace: &Place<'tcx>,
1195 _aggre_did: DefId,
1196 vidx: VariantIdx,
1197 disc: Disc,
1198 bidx: usize,
1199 sidx: usize,
1200 ) {
1201 let llocal = lplace.local;
1202 let lu: usize = llocal.as_usize();
1203
1204 if self.icx_slice.var()[lu].is_unsupported() {
1205 return;
1206 }
1207
1208 let l_local_ty = self.body.local_decls[llocal].ty;
1209 let default_heap = self.extract_default_ty_layout(l_local_ty, Some(vidx));
1210 if !default_heap.get_requirement() || default_heap.is_empty() {
1211 return;
1212 }
1213
1214 let llen = default_heap.layout().len();
1215 self.icx_slice_mut().len_mut()[lu] = llen;
1216
1217 if !self.icx_slice().var[lu].is_init() {
1218 let l_ori_name_ctor = new_local_name(lu, bidx, sidx).add("_ctor_asgn");
1219 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
1220 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
1221 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
1222 goal.assert(&constraint_l_ctor_zero);
1223 solver.assert(&constraint_l_ctor_zero);
1224 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, disc);
1225 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_ori_bv_ctor);
1226 }
1227 }
1228
1229 pub(crate) fn handle_copy_to_field(
1230 &mut self,
1231 ctx: &'ctx z3::Context,
1232 goal: &'ctx z3::Goal<'ctx>,
1233 solver: &'ctx z3::Solver<'ctx>,
1234 _kind: AsgnKind,
1235 lplace: &Place<'tcx>,
1236 rplace: &Place<'tcx>,
1237 mut disc: Disc,
1238 aggre: Aggre,
1239 bidx: usize,
1240 sidx: usize,
1241 ) {
1242 let llocal = lplace.local;
1245 let rlocal = rplace.local;
1246
1247 let lu: usize = llocal.as_usize();
1248 let ru: usize = rlocal.as_usize();
1249
1250 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
1252 {
1253 self.handle_intra_var_unsupported(lu);
1254 self.handle_intra_var_unsupported(ru);
1255 return;
1256 }
1257 if !self.icx_slice().var()[ru].is_init() {
1258 return;
1259 }
1260
1261 let l_local_ty = self.body.local_decls[llocal].ty;
1263 let lpj_fields = self.extract_projection(lplace, aggre);
1264 if lpj_fields.is_unsupported() {
1265 self.handle_intra_var_unsupported(lu);
1267 self.handle_intra_var_unsupported(ru);
1268 return;
1269 }
1270
1271 match (lpj_fields.has_field(), lpj_fields.has_downcast()) {
1272 (true, true) => {
1273 disc = lpj_fields.downcast();
1275 let ty_with_index = TyWithIndex::new(l_local_ty, disc);
1276
1277 if ty_with_index.0.is_none() {
1278 return;
1279 }
1280
1281 if lpj_fields.index_needed() == 0 && ty_with_index.0.unwrap().0 == 1 {
1283 self.handle_copy(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1284 return;
1285 }
1286 }
1287 (true, false) => {
1288 }
1290 (false, true) => {
1291 return;
1293 }
1294 (false, false) => {
1295 self.handle_copy(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1296 return;
1297 }
1298 }
1299
1300 let index_needed = lpj_fields.index_needed();
1301
1302 let default_heap = self.extract_default_ty_layout(l_local_ty, disc);
1303 if !default_heap.get_requirement() || default_heap.is_empty() {
1304 return;
1305 }
1306
1307 let llen = default_heap.layout().len();
1309 self.icx_slice_mut().len_mut()[lu] = llen;
1310 let rlen = self.icx_slice().len()[ru];
1311
1312 if self.icx_slice().len[ru] == 0 {
1315 return;
1317 }
1318
1319 let l_ori_bv: ast::BV;
1321 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
1322
1323 if self.icx_slice().var()[lu].is_init() {
1324 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
1328 let extract_from_field = l_ori_bv.extract(index_needed as u32, index_needed as u32);
1329 if lu > self.body.arg_count {
1330 let l_f_zero_const = ast::BV::from_u64(ctx, 0, 1);
1331 let constraint_l_f_ori_zero = extract_from_field._safe_eq(&l_f_zero_const).unwrap();
1332 goal.assert(&constraint_l_f_ori_zero);
1333 solver.assert(&constraint_l_f_ori_zero);
1334 }
1335 } else {
1336 let l_ori_name_ctor = new_local_name(lu, bidx, sidx).add("_ctor_asgn");
1339 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
1340 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
1341 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
1342 goal.assert(&constraint_l_ctor_zero);
1343 solver.assert(&constraint_l_ctor_zero);
1344 l_ori_bv = l_ori_zero;
1345 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, disc);
1346 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout().clone();
1347 }
1348
1349 let l_name = new_local_name(lu, bidx, sidx);
1355 let r_name = new_local_name(ru, bidx, sidx);
1356
1357 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
1359 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
1360
1361 let r_zero_const = ast::BV::from_u64(ctx, 0, rlen as u32);
1362
1363 let r_owning = r_new_bv._safe_eq(&r_ori_bv).unwrap();
1368 let mut rust_bv_for_op_and = vec![true; llen];
1370 rust_bv_for_op_and[index_needed] = false;
1371 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1372 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, llen as u32);
1373 let after_op_and = l_ori_bv.bvand(&z3_bv_for_op_and);
1374 let lpj_non_owning = l_new_bv._safe_eq(&after_op_and).unwrap();
1375
1376 let args1 = &[&r_owning, &lpj_non_owning];
1377 let summary_1 = ast::Bool::and(ctx, args1);
1378
1379 let r_non_owning = r_new_bv._safe_eq(&r_zero_const).unwrap();
1382 let disjunction_r = r_ori_bv.bvredor();
1388 let mut final_bv: ast::BV;
1389
1390 if index_needed < llen - 1 {
1391 let end_part = l_ori_bv.extract((llen - 1) as u32, (index_needed + 1) as u32);
1392 final_bv = end_part.concat(&disjunction_r);
1393 } else {
1394 final_bv = disjunction_r;
1395 }
1396 if index_needed > 0 {
1397 let begin_part = l_ori_bv.extract((index_needed - 1) as u32, 0);
1398 final_bv = final_bv.concat(&begin_part);
1399 }
1400
1401 let lpj_shrink_owning = l_new_bv._safe_eq(&final_bv).unwrap();
1402
1403 let args2 = &[&r_non_owning, &lpj_shrink_owning];
1404 let summary_2 = ast::Bool::and(ctx, args2);
1405
1406 let args3 = &[&summary_1, &summary_2];
1408 let constraint_owning_now = ast::Bool::or(ctx, args3);
1409
1410 goal.assert(&constraint_owning_now);
1411 solver.assert(&constraint_owning_now);
1412
1413 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1415 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1416 self.handle_taint(lu, ru);
1417 }
1418
1419 pub(crate) fn handle_move_to_field(
1420 &mut self,
1421 ctx: &'ctx z3::Context,
1422 goal: &'ctx z3::Goal<'ctx>,
1423 solver: &'ctx z3::Solver<'ctx>,
1424 _kind: AsgnKind,
1425 lplace: &Place<'tcx>,
1426 rplace: &Place<'tcx>,
1427 mut disc: Disc,
1428 aggre: Aggre,
1429 bidx: usize,
1430 sidx: usize,
1431 ) {
1432 let llocal = lplace.local;
1435 let rlocal = rplace.local;
1436
1437 let lu: usize = llocal.as_usize();
1438 let ru: usize = rlocal.as_usize();
1439
1440 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
1442 {
1443 self.handle_intra_var_unsupported(lu);
1444 self.handle_intra_var_unsupported(ru);
1445 return;
1446 }
1447 if !self.icx_slice().var()[ru].is_init() {
1448 return;
1449 }
1450
1451 let l_local_ty = self.body.local_decls[llocal].ty;
1453 let lpj_fields = self.extract_projection(lplace, aggre);
1454 if lpj_fields.is_unsupported() {
1455 self.handle_intra_var_unsupported(lu);
1457 self.handle_intra_var_unsupported(ru);
1458 return;
1459 }
1460
1461 match (lpj_fields.has_field(), lpj_fields.has_downcast()) {
1462 (true, true) => {
1463 disc = lpj_fields.downcast();
1465 let ty_with_index = TyWithIndex::new(l_local_ty, disc);
1466
1467 if ty_with_index.0.is_none() {
1468 return;
1469 }
1470
1471 if lpj_fields.index_needed() == 0 && ty_with_index.0.unwrap().0 == 1 {
1473 self.handle_move(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1474 return;
1475 }
1476 }
1477 (true, false) => {
1478 }
1480 (false, true) => {
1481 return;
1483 }
1484 (false, false) => {
1485 self.handle_move(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1486 return;
1487 }
1488 }
1489
1490 let index_needed = lpj_fields.index_needed();
1491
1492 let mut default_heap = self.extract_default_ty_layout(l_local_ty, disc);
1493 if !default_heap.get_requirement() || default_heap.is_empty() {
1494 return;
1495 }
1496
1497 let llen = default_heap.layout().len();
1499 self.icx_slice_mut().len_mut()[lu] = llen;
1500 let rlen = self.icx_slice().len()[ru];
1501
1502 if self.icx_slice().len[ru] == 0 {
1505 return;
1507 }
1508
1509 let l_ori_bv: ast::BV;
1511 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
1512
1513 if self.icx_slice().var()[lu].is_init() {
1514 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
1519 let extract_from_field = l_ori_bv.extract(index_needed as u32, index_needed as u32);
1520 if lu > self.body.arg_count {
1521 let l_f_zero_const = ast::BV::from_u64(ctx, 0, 1);
1522 let constraint_l_f_ori_zero = extract_from_field._safe_eq(&l_f_zero_const).unwrap();
1523 goal.assert(&constraint_l_f_ori_zero);
1524 solver.assert(&constraint_l_f_ori_zero);
1525 }
1526 } else {
1527 let l_ori_name_ctor = new_local_name(lu, bidx, sidx).add("_ctor_asgn");
1530 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
1531 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
1532 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
1533 goal.assert(&constraint_l_ctor_zero);
1534 solver.assert(&constraint_l_ctor_zero);
1535 l_ori_bv = l_ori_zero;
1536 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, disc);
1537 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout_mut().clone();
1538 }
1539
1540 let l_name = new_local_name(lu, bidx, sidx);
1546 let r_name = new_local_name(ru, bidx, sidx);
1547
1548 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
1550 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
1551
1552 let r_zero_const = ast::BV::from_u64(ctx, 0, rlen as u32);
1553
1554 let r_non_owning = r_new_bv._safe_eq(&r_zero_const).unwrap();
1558
1559 let disjunction_r = r_ori_bv.bvredor();
1565 let mut final_bv: ast::BV;
1566 if index_needed < llen - 1 {
1567 let end_part = l_ori_bv.extract((llen - 1) as u32, (index_needed + 1) as u32);
1568 final_bv = end_part.concat(&disjunction_r);
1569 } else {
1570 final_bv = disjunction_r;
1571 }
1572 if index_needed > 0 {
1573 let begin_part = l_ori_bv.extract((index_needed - 1) as u32, 0);
1574 final_bv = final_bv.concat(&begin_part);
1575 }
1576 let lpj_shrink_owning = l_new_bv._safe_eq(&final_bv).unwrap();
1577
1578 goal.assert(&r_non_owning);
1579 goal.assert(&lpj_shrink_owning);
1580 solver.assert(&r_non_owning);
1581 solver.assert(&lpj_shrink_owning);
1582
1583 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1585 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1586 self.handle_taint(lu, ru);
1587 }
1588
1589 pub(crate) fn handle_copy_field_to_field(
1590 &mut self,
1591 ctx: &'ctx z3::Context,
1592 goal: &'ctx z3::Goal<'ctx>,
1593 solver: &'ctx z3::Solver<'ctx>,
1594 _kind: AsgnKind,
1595 lplace: &Place<'tcx>,
1596 rplace: &Place<'tcx>,
1597 disc: Disc,
1598 aggre: Aggre,
1599 bidx: usize,
1600 sidx: usize,
1601 ) {
1602 let llocal = lplace.local;
1604 let rlocal = rplace.local;
1605
1606 let lu: usize = llocal.as_usize();
1607 let ru: usize = rlocal.as_usize();
1608
1609 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
1611 {
1612 self.handle_intra_var_unsupported(lu);
1613 self.handle_intra_var_unsupported(ru);
1614 return;
1615 }
1616 if !self.icx_slice().var()[ru].is_init() {
1617 return;
1618 }
1619
1620 let l_local_ty = self.body.local_decls[llocal].ty;
1621
1622 let rpj_fields = self.extract_projection(rplace, None);
1625 if rpj_fields.is_unsupported() {
1626 self.handle_intra_var_unsupported(lu);
1628 self.handle_intra_var_unsupported(ru);
1629 return;
1630 }
1631
1632 let lpj_fields = self.extract_projection(lplace, aggre);
1633 if lpj_fields.is_unsupported() {
1634 self.handle_intra_var_unsupported(lu);
1636 self.handle_intra_var_unsupported(ru);
1637 return;
1638 }
1639
1640 match (rpj_fields.has_field(), lpj_fields.has_field()) {
1641 (true, true) => (),
1642 (true, false) => {
1643 self.handle_copy_from_field(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1644 return;
1645 }
1646 (false, true) => {
1647 self.handle_copy_to_field(
1648 ctx, goal, solver, _kind, lplace, rplace, disc, aggre, bidx, sidx,
1649 );
1650 return;
1651 }
1652 (false, false) => {
1653 self.handle_copy(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1654 return;
1655 }
1656 }
1657
1658 let r_index_needed = rpj_fields.index_needed();
1659 let l_index_needed = lpj_fields.index_needed();
1660
1661 let default_heap = self.extract_default_ty_layout(l_local_ty, disc);
1662 if !default_heap.get_requirement() || default_heap.is_empty() {
1663 return;
1664 }
1665
1666 let llen = default_heap.layout().len();
1668 let rlen = self.icx_slice().len()[ru];
1669 self.icx_slice_mut().len_mut()[lu] = llen;
1670
1671 if self.icx_slice().len[ru] == 0 {
1674 return;
1676 }
1677
1678 let l_ori_bv: ast::BV;
1680 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
1681
1682 if self.icx_slice().var()[lu].is_init() {
1683 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
1687 let extract_from_field = l_ori_bv.extract(l_index_needed as u32, l_index_needed as u32);
1688 if lu > self.body.arg_count {
1689 let l_f_zero_const = ast::BV::from_u64(ctx, 0, 1);
1690 let constraint_l_f_ori_zero = extract_from_field._safe_eq(&l_f_zero_const).unwrap();
1691 goal.assert(&constraint_l_f_ori_zero);
1692 solver.assert(&constraint_l_f_ori_zero);
1693 }
1694 } else {
1695 let l_ori_name_ctor = new_local_name(lu, bidx, sidx).add("_ctor_asgn");
1698 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
1699 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
1700 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
1701 goal.assert(&constraint_l_ctor_zero);
1702 solver.assert(&constraint_l_ctor_zero);
1703 l_ori_bv = l_ori_zero;
1704 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, disc);
1705 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout().clone();
1706 }
1707
1708 let l_name = new_local_name(lu, bidx, sidx);
1710 let r_name = new_local_name(ru, bidx, sidx);
1711
1712 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
1714 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
1715
1716 let mut rust_bv_for_op_and = vec![true; rlen];
1723 rust_bv_for_op_and[r_index_needed] = false;
1724 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1725 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, rlen as u32);
1726 let after_op_and = r_ori_bv.bvand(&z3_bv_for_op_and);
1727 let rpj_non_owning = r_new_bv._safe_eq(&after_op_and).unwrap();
1728 let extract_field_r = r_ori_bv.extract(r_index_needed as u32, r_index_needed as u32);
1733 let mut final_bv: ast::BV;
1734 if l_index_needed < llen - 1 {
1735 let end_part = l_ori_bv.extract((llen - 1) as u32, (l_index_needed + 1) as u32);
1736 final_bv = end_part.concat(&extract_field_r);
1737 } else {
1738 final_bv = extract_field_r;
1739 }
1740 if l_index_needed > 0 {
1741 let begin_part = l_ori_bv.extract((l_index_needed - 1) as u32, 0);
1742 final_bv = final_bv.concat(&begin_part);
1743 }
1744 let lpj_owning = l_new_bv._safe_eq(&final_bv).unwrap();
1745
1746 let args1 = &[&rpj_non_owning, &lpj_owning];
1747 let summary_1 = ast::Bool::and(ctx, args1);
1748
1749 let mut rust_bv_for_op_and = vec![true; llen];
1752 rust_bv_for_op_and[l_index_needed] = false;
1753 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1754 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, llen as u32);
1755 let after_op_and = l_ori_bv.bvand(&z3_bv_for_op_and);
1756 let lpj_non_owning = l_new_bv._safe_eq(&after_op_and).unwrap();
1757 let rpj_owning = r_new_bv._safe_eq(&r_ori_bv).unwrap();
1759
1760 let args2 = &[&lpj_non_owning, &rpj_owning];
1761 let summary_2 = ast::Bool::and(ctx, args2);
1762
1763 let args3 = &[&summary_1, &summary_2];
1765 let constraint_owning_now = ast::Bool::or(ctx, args3);
1766
1767 goal.assert(&constraint_owning_now);
1768 solver.assert(&constraint_owning_now);
1769
1770 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1772 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1773 self.handle_taint(lu, ru);
1774 }
1775
1776 pub(crate) fn handle_move_field_to_field(
1777 &mut self,
1778 ctx: &'ctx z3::Context,
1779 goal: &'ctx z3::Goal<'ctx>,
1780 solver: &'ctx z3::Solver<'ctx>,
1781 _kind: AsgnKind,
1782 lplace: &Place<'tcx>,
1783 rplace: &Place<'tcx>,
1784 disc: Disc,
1785 aggre: Aggre,
1786 bidx: usize,
1787 sidx: usize,
1788 ) {
1789 let llocal = lplace.local;
1791 let rlocal = rplace.local;
1792
1793 let lu: usize = llocal.as_usize();
1794 let ru: usize = rlocal.as_usize();
1795
1796 if self.icx_slice().var()[lu].is_unsupported() || self.icx_slice.var()[ru].is_unsupported()
1798 {
1799 self.handle_intra_var_unsupported(lu);
1800 self.handle_intra_var_unsupported(ru);
1801 return;
1802 }
1803 if !self.icx_slice().var()[ru].is_init() {
1804 return;
1805 }
1806
1807 let l_local_ty = self.body.local_decls[llocal].ty;
1808
1809 let rpj_fields = self.extract_projection(rplace, None);
1813 if rpj_fields.is_unsupported() {
1814 self.handle_intra_var_unsupported(lu);
1816 self.handle_intra_var_unsupported(ru);
1817 return;
1818 }
1819
1820 let lpj_fields = self.extract_projection(lplace, aggre);
1824 if lpj_fields.is_unsupported() {
1825 self.handle_intra_var_unsupported(lu);
1827 self.handle_intra_var_unsupported(ru);
1828 return;
1829 }
1830
1831 match (rpj_fields.has_field(), lpj_fields.has_field()) {
1832 (true, true) => (),
1833 (true, false) => {
1834 self.handle_move_from_field(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1835 return;
1836 }
1837 (false, true) => {
1838 self.handle_move_to_field(
1839 ctx, goal, solver, _kind, lplace, rplace, disc, aggre, bidx, sidx,
1840 );
1841 }
1842 (false, false) => {
1843 self.handle_move(ctx, goal, solver, _kind, lplace, rplace, bidx, sidx);
1844 return;
1845 }
1846 }
1847
1848 let r_index_needed = rpj_fields.index_needed();
1849 let l_index_needed = lpj_fields.index_needed();
1850
1851 let default_heap = self.extract_default_ty_layout(l_local_ty, disc);
1852 if !default_heap.get_requirement() || default_heap.is_empty() {
1853 return;
1854 }
1855
1856 let llen = default_heap.layout().len();
1858 let rlen = self.icx_slice().len()[ru];
1859 self.icx_slice_mut().len_mut()[lu] = llen;
1860
1861 if self.icx_slice().len[ru] == 0 {
1864 return;
1866 }
1867
1868 let l_ori_bv: ast::BV;
1870 let r_ori_bv = self.icx_slice_mut().var_mut()[ru].extract();
1871
1872 if self.icx_slice().var()[lu].is_init() {
1873 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
1877 let extract_from_field = l_ori_bv.extract(l_index_needed as u32, l_index_needed as u32);
1878 if lu > self.body.arg_count {
1879 let l_f_zero_const = ast::BV::from_u64(ctx, 0, 1);
1880 let constraint_l_f_ori_zero = extract_from_field._safe_eq(&l_f_zero_const).unwrap();
1881 goal.assert(&constraint_l_f_ori_zero);
1882 solver.assert(&constraint_l_f_ori_zero);
1883 }
1884 } else {
1885 let l_ori_name_ctor = new_local_name(lu, bidx, sidx).add("_ctor_asgn");
1888 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
1889 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
1890 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
1891 goal.assert(&constraint_l_ctor_zero);
1892 solver.assert(&constraint_l_ctor_zero);
1893 l_ori_bv = l_ori_zero;
1894 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, disc);
1895 self.icx_slice_mut().layout_mut()[lu] = default_heap.layout().clone();
1896 }
1897
1898 let l_name = new_local_name(lu, bidx, sidx);
1900 let r_name = new_local_name(ru, bidx, sidx);
1901
1902 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
1904 let r_new_bv = ast::BV::new_const(ctx, r_name, rlen as u32);
1905
1906 let mut rust_bv_for_op_and = vec![true; rlen];
1912 rust_bv_for_op_and[r_index_needed] = false;
1913 let int_for_op_and = rustbv_to_int(&rust_bv_for_op_and);
1914 let z3_bv_for_op_and = ast::BV::from_u64(ctx, int_for_op_and, rlen as u32);
1915 let after_op_and = r_ori_bv.bvand(&z3_bv_for_op_and);
1916 let rpj_non_owning = r_new_bv._safe_eq(&after_op_and).unwrap();
1917
1918 let extract_field_r = r_ori_bv.extract(r_index_needed as u32, r_index_needed as u32);
1923 let mut final_bv: ast::BV;
1924
1925 if l_index_needed < llen - 1 {
1926 let end_part = l_ori_bv.extract((llen - 1) as u32, (l_index_needed + 1) as u32);
1927 final_bv = end_part.concat(&extract_field_r);
1928 } else {
1929 final_bv = extract_field_r;
1930 }
1931 if l_index_needed > 0 {
1932 let begin_part = l_ori_bv.extract((l_index_needed - 1) as u32, 0);
1933 final_bv = final_bv.concat(&begin_part);
1934 }
1935 let lpj_owning = l_new_bv._safe_eq(&final_bv).unwrap();
1936
1937 goal.assert(&rpj_non_owning);
1938 goal.assert(&lpj_owning);
1939 solver.assert(&rpj_non_owning);
1940 solver.assert(&lpj_owning);
1941
1942 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
1944 self.icx_slice_mut().var_mut()[ru] = IntraVar::Init(r_new_bv);
1945 self.handle_taint(lu, ru);
1946 }
1947
1948 pub(crate) fn check_fn_source(
1949 &mut self,
1950 args: &Box<[Spanned<Operand<'tcx>>]>,
1952 dest: &Place<'tcx>,
1953 ) -> bool {
1954 if args.len() != 1 {
1955 return false;
1956 }
1957
1958 let l_place_ty = dest.ty(&self.body.local_decls, self.tcx());
1959 if !is_place_containing_ptr(&l_place_ty.ty) {
1960 return false;
1961 }
1962
1963 match args[0].node {
1964 Operand::Move(aplace) => {
1965 let a_place_ty = aplace.ty(&self.body.local_decls, self.tcx());
1966 let default_layout =
1967 self.extract_default_ty_layout(a_place_ty.ty, a_place_ty.variant_index);
1968 if default_layout.is_owned() {
1969 self.taint_flag = true;
1970 true
1971 } else {
1972 false
1973 }
1974 }
1975 _ => false,
1976 }
1977 }
1978
1979 pub(crate) fn check_fn_recovery(
1980 &mut self,
1981 args: &Box<[Spanned<Operand<'tcx>>]>,
1983 dest: &Place<'tcx>,
1984 ) -> (bool, Vec<usize>) {
1985 let mut ans: (bool, Vec<usize>) = (false, Vec::new());
1986
1987 if args.len() == 0 {
1988 return ans;
1989 }
1990
1991 let l_place_ty = dest.ty(&self.body.local_decls, self.tcx());
1992 let default_layout =
1993 self.extract_default_ty_layout(l_place_ty.ty, l_place_ty.variant_index);
1994 if !default_layout.get_requirement() || default_layout.is_empty() {
1995 return ans;
1996 }
1997 let ty_with_idx = TyWithIndex::new(l_place_ty.ty, l_place_ty.variant_index);
1998
1999 for arg in args {
2000 match arg.node {
2001 Operand::Move(aplace) => {
2002 let au: usize = aplace.local.as_usize();
2003 let taint = &self.icx_slice().taint()[au];
2004 if taint.is_tainted() && taint.contains(&ty_with_idx) {
2005 ans.0 = true;
2006 ans.1.push(au);
2007 }
2008 }
2009 Operand::Copy(aplace) => {
2010 let au: usize = aplace.local.as_usize();
2011 let taint = &self.icx_slice().taint()[au];
2012 if taint.is_tainted() && taint.contains(&ty_with_idx) {
2013 ans.0 = true;
2014 ans.1.push(au);
2015 }
2016 }
2017 _ => (),
2018 }
2019 }
2020 ans
2021 }
2022
2023 pub(crate) fn handle_call(
2024 &mut self,
2025 ctx: &'ctx z3::Context,
2026 goal: &'ctx z3::Goal<'ctx>,
2027 solver: &'ctx z3::Solver<'ctx>,
2028 term: Terminator<'tcx>,
2029 func: &Operand<'tcx>,
2030 args: &Box<[Spanned<Operand<'tcx>>]>,
2032 dest: &Place<'tcx>,
2033 bidx: usize,
2034 ) {
2035 match func {
2036 Operand::Constant(constant) => {
2037 match constant.ty().kind() {
2038 ty::FnDef(id, ..) => {
2039 match id.index.as_usize() {
2042 2171 => {
2043 match args[0].node {
2045 Operand::Move(aplace) => {
2046 let a_place_ty =
2047 dest.ty(&self.body.local_decls, self.tcx());
2048 let a_ty = a_place_ty.ty;
2049 if a_ty.is_adt() {
2050 self.handle_drop(
2051 ctx, goal, solver, &aplace, bidx, false,
2052 );
2053 return;
2054 }
2055 }
2056 _ => (),
2057 }
2058 }
2059 _ => (),
2060 }
2061 }
2062 _ => (),
2063 }
2064 }
2065 _ => (),
2066 }
2067
2068 let llocal = dest.local;
2070 let lu: usize = llocal.as_usize();
2071
2072 let source_flag = self.check_fn_source(args, dest);
2075 let recovery_flag = self.check_fn_recovery(args, dest);
2079 if source_flag {
2080 self.add_taint(term);
2081 }
2082
2083 for arg in args {
2084 match arg.node {
2085 Operand::Move(aplace) => {
2086 let alocal = aplace.local;
2087 let au: usize = alocal.as_usize();
2088
2089 if self.icx_slice().len()[au] == 0 {
2092 continue;
2094 }
2095
2096 if !self.icx_slice().var()[au].is_init() {
2097 continue;
2098 }
2099
2100 let a_place_ty = aplace.ty(&self.body.local_decls, self.tcx());
2101 let a_ty = a_place_ty.ty;
2102 let is_a_ptr = a_ty.is_any_ptr();
2103
2104 let a_ori_bv = self.icx_slice_mut().var_mut()[au].extract();
2105 let alen = self.icx_slice().len()[au];
2106
2107 if source_flag {
2108 self.icx_slice_mut().taint_mut()[lu]
2109 .insert(TyWithIndex::new(a_place_ty.ty, a_place_ty.variant_index));
2110 }
2111
2112 match aplace.projection.len() {
2113 0 => {
2114 if is_a_ptr {
2116 if recovery_flag.0 && recovery_flag.1.contains(&au) {
2117 self.handle_drop(ctx, goal, solver, &aplace, bidx, true);
2118 continue;
2119 }
2120
2121 let a_zero_const = ast::BV::from_u64(ctx, 0, alen as u32);
2125 let a_ori_non_owing = a_ori_bv._safe_eq(&a_zero_const).unwrap();
2126
2127 let a_name = new_local_name(au, bidx, 0).add("_param_pass");
2129 let a_new_bv = ast::BV::new_const(ctx, a_name, alen as u32);
2130 let update_a = a_new_bv._safe_eq(&a_ori_bv).unwrap();
2131
2132 goal.assert(&a_ori_non_owing);
2133 goal.assert(&update_a);
2134 solver.assert(&a_ori_non_owing);
2135 solver.assert(&update_a);
2136
2137 self.icx_slice_mut().var_mut()[au] = IntraVar::Init(a_new_bv);
2138 } else {
2139 self.handle_drop(ctx, goal, solver, &aplace, bidx, false);
2141 }
2142 }
2143 1 => {
2144 if is_a_ptr {
2146 if recovery_flag.0 && recovery_flag.1.contains(&au) {
2147 self.handle_drop(ctx, goal, solver, &aplace, bidx, true);
2148 continue;
2149 }
2150 let a_name = new_local_name(au, bidx, 0).add("_param_pass");
2154 let a_new_bv = ast::BV::new_const(ctx, a_name, alen as u32);
2155 let update_a = a_new_bv._safe_eq(&a_ori_bv).unwrap();
2156
2157 goal.assert(&update_a);
2158 solver.assert(&update_a);
2159 } else {
2160 self.handle_drop(ctx, goal, solver, &aplace, bidx, false);
2162 }
2163 }
2164 _ => {
2165 self.handle_intra_var_unsupported(au);
2166 continue;
2167 }
2168 }
2169 }
2170 Operand::Copy(aplace) => {
2171 let alocal = aplace.local;
2172 let au: usize = alocal.as_usize();
2173
2174 if self.icx_slice().len()[au] == 0 {
2177 continue;
2179 }
2180
2181 if !self.icx_slice().var()[au].is_init() {
2182 continue;
2183 }
2184
2185 let a_ty = aplace.ty(&self.body.local_decls, self.tcx()).ty;
2186 let is_a_ptr = a_ty.is_any_ptr();
2187
2188 let a_ori_bv = self.icx_slice_mut().var_mut()[au].extract();
2189 let alen = self.icx_slice().len()[au];
2190
2191 match aplace.projection.len() {
2192 0 => {
2193 if is_a_ptr {
2195 if recovery_flag.0 && recovery_flag.1.contains(&au) {
2196 self.handle_drop(ctx, goal, solver, &aplace, bidx, true);
2197 continue;
2198 }
2199
2200 let a_zero_const = ast::BV::from_u64(ctx, 0, alen as u32);
2204 let a_ori_non_owing = a_ori_bv._safe_eq(&a_zero_const).unwrap();
2205
2206 let a_name = new_local_name(au, bidx, 0).add("_param_pass");
2208 let a_new_bv = ast::BV::new_const(ctx, a_name, alen as u32);
2209 let update_a = a_new_bv._safe_eq(&a_ori_bv).unwrap();
2210
2211 goal.assert(&a_ori_non_owing);
2212 goal.assert(&update_a);
2213 solver.assert(&a_ori_non_owing);
2214 solver.assert(&update_a);
2215
2216 self.icx_slice_mut().var_mut()[au] = IntraVar::Init(a_new_bv);
2217 } else {
2218 if is_a_ptr {
2222 if recovery_flag.0 && recovery_flag.1.contains(&au) {
2223 self.handle_drop(ctx, goal, solver, &aplace, bidx, true);
2224 continue;
2225 }
2226 }
2227
2228 let a_name = new_local_name(au, bidx, 0).add("_param_pass");
2229 let a_new_bv = ast::BV::new_const(ctx, a_name, alen as u32);
2230 let update_a = a_new_bv._safe_eq(&a_ori_bv).unwrap();
2231
2232 goal.assert(&update_a);
2233 solver.assert(&update_a);
2234 }
2235 }
2236 1 => {
2237 let a_name = new_local_name(au, bidx, 0).add("_param_pass");
2239 let a_new_bv = ast::BV::new_const(ctx, a_name, alen as u32);
2240 let update_a = a_new_bv._safe_eq(&a_ori_bv).unwrap();
2241
2242 goal.assert(&update_a);
2243 solver.assert(&update_a);
2244 }
2245 _ => {
2246 self.handle_intra_var_unsupported(au);
2247 continue;
2248 }
2249 }
2250 }
2251 Operand::Constant(..) => continue,
2252 }
2253 }
2254
2255 if self.icx_slice().var()[lu].is_unsupported() {
2257 self.handle_intra_var_unsupported(lu);
2258 return;
2259 }
2260
2261 let l_ori_bv: ast::BV;
2262
2263 let l_place_ty = dest.ty(&self.body.local_decls, self.tcx());
2264 let l_local_ty = self.body.local_decls[llocal].ty;
2265
2266 let mut is_ctor = true;
2267 match dest.projection.len() {
2268 0 => {
2269 let return_value_layout =
2272 self.extract_default_ty_layout(l_place_ty.ty, l_place_ty.variant_index);
2273 if return_value_layout.is_empty() || !return_value_layout.get_requirement() {
2274 return;
2275 }
2276
2277 let int_for_gen = if source_flag {
2278 let modified_layout_bv =
2279 self.generate_ptr_layout(l_place_ty.ty, l_place_ty.variant_index);
2280 let merge_layout_bv = rustbv_merge(
2281 &heap_layout_to_rustbv(return_value_layout.layout()),
2282 &modified_layout_bv,
2283 );
2284 rustbv_to_int(&merge_layout_bv)
2285 } else {
2286 rustbv_to_int(&heap_layout_to_rustbv(return_value_layout.layout()))
2287 };
2288
2289 let mut llen = self.icx_slice().len()[lu];
2290
2291 if self.icx_slice().var()[lu].is_init() {
2292 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
2293 let l_zero_const = ast::BV::from_u64(ctx, 0, llen as u32);
2294 let constraint_l_ori_zero = l_ori_bv._safe_eq(&l_zero_const).unwrap();
2295 goal.assert(&constraint_l_ori_zero);
2296 solver.assert(&constraint_l_ori_zero);
2297 is_ctor = false;
2298 } else {
2299 let ty_with_vidx = TyWithIndex::new(l_place_ty.ty, l_place_ty.variant_index);
2301 match ty_with_vidx.get_priority() {
2302 0 => {
2303 self.handle_intra_var_unsupported(lu);
2305 return;
2306 }
2307 1 => {
2308 return;
2309 }
2310 2 => {
2311 self.icx_slice_mut().ty_mut()[lu] = ty_with_vidx;
2313 self.icx_slice_mut().layout_mut()[lu] =
2314 return_value_layout.layout().clone();
2315 }
2316 _ => unreachable!(),
2317 }
2318 }
2319
2320 llen = return_value_layout.layout().len();
2321
2322 let l_name = if is_ctor {
2323 new_local_name(lu, bidx, 0).add("_ctor_fn")
2324 } else {
2325 new_local_name(lu, bidx, 0).add("_cover_fn")
2326 };
2327
2328 let l_layout_bv = ast::BV::from_u64(ctx, int_for_gen, llen as u32);
2329 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
2330
2331 let constraint_new_owning = l_new_bv._safe_eq(&l_layout_bv).unwrap();
2332
2333 goal.assert(&constraint_new_owning);
2334 solver.assert(&constraint_new_owning);
2335
2336 self.icx_slice_mut().len_mut()[lu] = llen;
2337 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
2338 }
2339 1 => {
2340 let return_value_layout = self.extract_default_ty_layout(l_local_ty, None);
2343 if return_value_layout.is_empty() || !return_value_layout.get_requirement() {
2344 return;
2345 }
2346
2347 let llen = self.icx_slice().len()[lu];
2350
2351 let lpj_fields = self.extract_projection(dest, None);
2352 let index_needed = lpj_fields.index_needed();
2353
2354 if self.icx_slice().var()[lu].is_init() {
2355 l_ori_bv = self.icx_slice_mut().var_mut()[lu].extract();
2356 let extract_from_field =
2357 l_ori_bv.extract(index_needed as u32, index_needed as u32);
2358 let l_f_zero_const = ast::BV::from_u64(ctx, 0, 1);
2359 let constraint_l_f_ori_zero =
2360 extract_from_field._safe_eq(&l_f_zero_const).unwrap();
2361
2362 goal.assert(&constraint_l_f_ori_zero);
2363 solver.assert(&constraint_l_f_ori_zero);
2364 } else {
2365 let l_ori_name_ctor = new_local_name(lu, bidx, 0).add("_ctor_fn");
2366 let l_ori_bv_ctor = ast::BV::new_const(ctx, l_ori_name_ctor, llen as u32);
2367 let l_ori_zero = ast::BV::from_u64(ctx, 0, llen as u32);
2368 let constraint_l_ctor_zero = l_ori_bv_ctor._safe_eq(&l_ori_zero).unwrap();
2369
2370 goal.assert(&constraint_l_ctor_zero);
2371 solver.assert(&constraint_l_ctor_zero);
2372
2373 l_ori_bv = l_ori_zero;
2374 self.icx_slice_mut().ty_mut()[lu] = TyWithIndex::new(l_local_ty, None);
2375 self.icx_slice_mut().layout_mut()[lu] = return_value_layout.layout().clone();
2376 }
2377
2378 let l_name = new_local_name(lu, bidx, 0);
2379 let l_new_bv = ast::BV::new_const(ctx, l_name, llen as u32);
2380
2381 let update_field = if source_flag {
2382 ast::BV::from_u64(ctx, 1, 1)
2383 } else {
2384 if return_value_layout.layout()[index_needed] == OwnedHeap::True {
2385 ast::BV::from_u64(ctx, 1, 1)
2386 } else {
2387 ast::BV::from_u64(ctx, 0, 1)
2388 }
2389 };
2390
2391 let mut final_bv: ast::BV;
2392 if index_needed < llen - 1 {
2393 let end_part = l_ori_bv.extract((llen - 1) as u32, (index_needed + 1) as u32);
2394 final_bv = end_part.concat(&update_field);
2395 } else {
2396 final_bv = update_field;
2397 }
2398 if index_needed > 0 {
2399 let begin_part = l_ori_bv.extract((index_needed - 1) as u32, 0);
2400 final_bv = final_bv.concat(&begin_part);
2401 }
2402 let update_filed_using_func = l_new_bv._safe_eq(&final_bv).unwrap();
2403
2404 goal.assert(&update_filed_using_func);
2405 solver.assert(&update_filed_using_func);
2406
2407 self.icx_slice_mut().len_mut()[lu] = return_value_layout.layout().len();
2408 self.icx_slice_mut().var_mut()[lu] = IntraVar::Init(l_new_bv);
2409 }
2410 _ => {
2411 self.handle_intra_var_unsupported(lu);
2412 return;
2413 }
2414 }
2415 }
2416
2417 pub(crate) fn handle_return(
2418 &mut self,
2419 ctx: &'ctx z3::Context,
2420 goal: &'ctx z3::Goal<'ctx>,
2421 solver: &'ctx z3::Solver<'ctx>,
2422 bidx: usize,
2423 ) {
2424 let place_0 = Place::from(Local::from_usize(0));
2425 self.handle_drop(ctx, goal, solver, &place_0, bidx, false);
2426
2427 for (iidx, var) in self.icx_slice().var.iter().enumerate() {
2429 let len = self.icx_slice().len()[iidx];
2430 if len == 0 {
2431 continue;
2432 }
2433 if iidx <= self.body.arg_count {
2434 continue;
2435 }
2436
2437 if var.is_init() {
2438 let var_ori_bv = var.extract();
2439
2440 let return_name = new_local_name(iidx, bidx, 0).add("_return");
2441 let var_return_bv = ast::BV::new_const(ctx, return_name, len as u32);
2442
2443 let zero_const = ast::BV::from_u64(ctx, 0, len as u32);
2444
2445 let var_update = var_return_bv._safe_eq(&var_ori_bv).unwrap();
2446 let var_freed = var_return_bv._safe_eq(&zero_const).unwrap();
2447
2448 let args = &[&var_update, &var_freed];
2449 let constraint_return = ast::Bool::and(ctx, args);
2450
2451 goal.assert(&constraint_return);
2452 solver.assert(&constraint_return);
2453 }
2454 }
2455
2456 let result = solver.check();
2457 let model = solver.get_model();
2458
2459 if is_z3_goal_verbose() {
2460 let g = format!("{}", goal);
2461 rap_trace!("{}\n", g);
2462 if model.is_some() {
2463 rap_trace!("{}", format!("{}", model.unwrap()));
2464 }
2465 }
2466
2467 if result == z3::SatResult::Unsat && self.taint_flag {
2473 let fn_name = get_name(self.tcx(), self.def_id)
2474 .unwrap_or_else(|| Symbol::intern("no symbol available"));
2475
2476 rap_warn!("Memory Leak detected in function {:}", fn_name);
2477 let source = span_to_source_code(self.body.span);
2478 let file = span_to_filename(self.body.span);
2479 let mut snippet = Snippet::source(&source)
2480 .line_start(span_to_line_number(self.body.span))
2481 .origin(&file)
2482 .fold(false);
2483
2484 for source in self.taint_source.iter() {
2485 if are_spans_in_same_file(self.body.span, source.source_info.span) {
2486 snippet = snippet.annotation(
2487 Level::Warning
2488 .span(relative_pos_range(self.body.span, source.source_info.span))
2489 .label("Memory Leak Candidates."),
2490 );
2491 }
2492 }
2500
2501 let message = Level::Warning
2502 .title("Memory Leak detected.")
2503 .snippet(snippet);
2504 let renderer = Renderer::styled();
2505 println!("{}", renderer.render(message));
2506 }
2507 }
2508
2509 pub(crate) fn handle_drop(
2510 &mut self,
2511 ctx: &'ctx z3::Context,
2512 goal: &'ctx z3::Goal<'ctx>,
2513 solver: &'ctx z3::Solver<'ctx>,
2514 dest: &Place<'tcx>,
2515 bidx: usize,
2516 recovery: bool,
2517 ) {
2518 let local = dest.local;
2519 let u: usize = local.as_usize();
2520
2521 if self.icx_slice().len()[u] == 0 {
2522 return;
2523 }
2524
2525 if self.icx_slice().var()[u].is_declared() || self.icx_slice().var()[u].is_unsupported() {
2526 return;
2527 }
2528
2529 let len = self.icx_slice().len()[u];
2530 let rust_bv = reverse_heap_layout_to_rustbv(&self.icx_slice().layout()[u]);
2531 let ori_bv = self.icx_slice().var()[u].extract();
2532
2533 let f = self.extract_projection(dest, None);
2534 if f.is_unsupported() {
2535 self.handle_intra_var_unsupported(u);
2536 return;
2537 }
2538
2539 match f.has_field() {
2540 false => {
2541 if recovery {
2544 let name = new_local_name(u, bidx, 0).add("_drop_recovery");
2546 let new_bv = ast::BV::new_const(ctx, name, len as u32);
2547 let zero_bv = ast::BV::from_u64(ctx, 0, len as u32);
2548
2549 let and_bv = ori_bv.bvand(&zero_bv);
2550
2551 let constraint_recovery = new_bv._eq(&and_bv);
2552
2553 goal.assert(&constraint_recovery);
2554 solver.assert(&constraint_recovery);
2555
2556 self.icx_slice_mut().var_mut()[u] = IntraVar::Init(new_bv);
2557 } else {
2558 let name = new_local_name(u, bidx, 0).add("_drop_all");
2560 let new_bv = ast::BV::new_const(ctx, name, len as u32);
2561 let int_for_rust_bv = rustbv_to_int(&rust_bv);
2562 let int_bv_const = ast::BV::from_u64(ctx, int_for_rust_bv, len as u32);
2563
2564 let and_bv = ori_bv.bvand(&int_bv_const);
2565
2566 let constraint_reverse = new_bv._eq(&and_bv);
2567
2568 goal.assert(&constraint_reverse);
2569 solver.assert(&constraint_reverse);
2570
2571 self.icx_slice_mut().var_mut()[u] = IntraVar::Init(new_bv);
2572 }
2573 }
2574 true => {
2575 let index_needed = f.index_needed();
2577
2578 if index_needed >= rust_bv.len() {
2579 return;
2580 }
2581
2582 let name = if recovery {
2583 new_local_name(u, bidx, 0).add("_drop_f_recovery")
2584 } else {
2585 new_local_name(u, bidx, 0).add("_drop_f")
2586 };
2587 let new_bv = ast::BV::new_const(ctx, name, len as u32);
2588
2589 if (rust_bv[index_needed] && !recovery) || (!rust_bv[index_needed] && recovery) {
2590 let constraint_update = new_bv._eq(&ori_bv);
2593
2594 goal.assert(&constraint_update);
2595 solver.assert(&constraint_update);
2596
2597 self.icx_slice_mut().var_mut()[u] = IntraVar::Init(new_bv);
2598 } else {
2599 let f_free = ast::BV::from_u64(ctx, 0, 1);
2600 let mut final_bv: ast::BV;
2601 if index_needed < len - 1 {
2602 let end_part = ori_bv.extract((len - 1) as u32, (index_needed + 1) as u32);
2603 final_bv = end_part.concat(&f_free);
2604 } else {
2605 final_bv = f_free;
2606 }
2607 if index_needed > 0 {
2608 let begin_part = ori_bv.extract((index_needed - 1) as u32, 0);
2609 final_bv = final_bv.concat(&begin_part);
2610 }
2611
2612 let constraint_free_f = new_bv._safe_eq(&final_bv).unwrap();
2613
2614 goal.assert(&constraint_free_f);
2615 solver.assert(&constraint_free_f);
2616
2617 self.icx_slice_mut().var_mut()[u] = IntraVar::Init(new_bv);
2618 }
2619 }
2620 }
2621 }
2622
2623 pub(crate) fn handle_intra_var_unsupported(&mut self, idx: usize) {
2624 match self.icx_slice_mut().var_mut()[idx] {
2625 IntraVar::Unsupported => return,
2626 IntraVar::Declared | IntraVar::Init(_) => {
2627 self.icx_slice_mut().var_mut()[idx] = IntraVar::Unsupported;
2629 self.icx_slice_mut().len_mut()[idx] = 0;
2630 return;
2631 }
2632 }
2633 }
2634
2635 pub(crate) fn handle_taint(&mut self, l: usize, r: usize) {
2636 if self.icx_slice().taint()[r].is_untainted() {
2637 return;
2638 }
2639
2640 if self.icx_slice().taint()[l].is_untainted() {
2641 self.icx_slice_mut().taint_mut()[l] = self.icx_slice().taint()[r].clone();
2642 } else {
2643 for elem in self.icx_slice().taint()[r].set().clone() {
2644 self.icx_slice_mut().taint_mut()[l].insert(elem);
2645 }
2646 }
2647 }
2648
2649 pub(crate) fn extract_default_ty_layout(
2650 &mut self,
2651 ty: Ty<'tcx>,
2652 variant: Option<VariantIdx>,
2653 ) -> OwnershipLayoutResult {
2654 match ty.kind() {
2655 TyKind::Array(..) => {
2656 let mut res = OwnershipLayoutResult::new();
2657 let mut default_heap = DefaultOwnership::new(self.tcx(), self.owner());
2658
2659 let _ = ty.visit_with(&mut default_heap);
2660 res.update_from_default_heap_visitor(&mut default_heap);
2661
2662 res
2663 }
2664 TyKind::Tuple(tuple_ty_list) => {
2665 let mut res = OwnershipLayoutResult::new();
2666
2667 for tuple_ty in tuple_ty_list.iter() {
2668 let mut default_heap = DefaultOwnership::new(self.tcx(), self.owner());
2669
2670 let _ = tuple_ty.visit_with(&mut default_heap);
2671 res.update_from_default_heap_visitor(&mut default_heap);
2672 }
2673
2674 res
2675 }
2676 TyKind::Adt(adtdef, substs) => {
2677 if adtdef.is_enum() && variant.is_none() {
2679 return OwnershipLayoutResult::new();
2680 }
2681
2682 let mut res = OwnershipLayoutResult::new();
2683
2684 if adtdef.is_struct() || adtdef.is_union() {
2686 for field in adtdef.all_fields() {
2687 let field_ty = field.ty(self.tcx(), substs);
2688
2689 let mut default_heap = DefaultOwnership::new(self.tcx(), self.owner());
2690
2691 let _ = field_ty.visit_with(&mut default_heap);
2692 res.update_from_default_heap_visitor(&mut default_heap);
2693 }
2694 }
2695 else if adtdef.is_enum() {
2697 let vidx = variant.unwrap();
2698
2699 for field in &adtdef.variants()[vidx].fields {
2700 let field_ty = field.ty(self.tcx(), substs);
2701
2702 let mut default_heap = DefaultOwnership::new(self.tcx(), self.owner());
2703
2704 let _ = field_ty.visit_with(&mut default_heap);
2705 res.update_from_default_heap_visitor(&mut default_heap);
2706 }
2707 }
2708 res
2709 }
2710 TyKind::Param(..) => {
2711 let mut res = OwnershipLayoutResult::new();
2712 res.set_requirement(true);
2713 res.set_param(true);
2714 res.set_owned(true);
2715 res.layout_mut().push(OwnedHeap::True);
2716 res
2717 }
2718 TyKind::RawPtr(..) => {
2719 let mut res = OwnershipLayoutResult::new();
2720 res.set_requirement(true);
2721 res.layout_mut().push(OwnedHeap::False);
2722 res
2723 }
2724 TyKind::Ref(..) => {
2725 let mut res = OwnershipLayoutResult::new();
2726 res.set_requirement(true);
2727 res.layout_mut().push(OwnedHeap::False);
2728 res
2729 }
2730 _ => OwnershipLayoutResult::new(),
2731 }
2732 }
2733
2734 pub(crate) fn generate_ptr_layout(
2735 &mut self,
2736 ty: Ty<'tcx>,
2737 variant: Option<VariantIdx>,
2738 ) -> Vec<bool> {
2739 let mut res = Vec::new();
2740 match ty.kind() {
2741 TyKind::Array(..) => {
2742 res.push(false);
2743 res
2744 }
2745 TyKind::Tuple(tuple_ty_list) => {
2746 for tuple_ty in tuple_ty_list.iter() {
2747 if tuple_ty.is_any_ptr() {
2748 res.push(true);
2749 } else {
2750 res.push(false);
2751 }
2752 }
2753
2754 res
2755 }
2756 TyKind::Adt(adtdef, _substs) => {
2757 if adtdef.is_enum() && variant.is_none() {
2759 return res;
2760 }
2761
2762 if adtdef.is_struct() || adtdef.is_union() {
2764 for _field in adtdef.all_fields() {
2765 res.push(false);
2766 }
2767 }
2768 else if adtdef.is_enum() {
2770 let vidx = variant.unwrap();
2771
2772 for _field in &adtdef.variants()[vidx].fields {
2773 res.push(false);
2774 }
2775 }
2776 res
2777 }
2778 TyKind::Param(..) => {
2779 res.push(false);
2780 res
2781 }
2782 TyKind::RawPtr(..) => {
2783 res.push(true);
2784 res
2785 }
2786 TyKind::Ref(..) => {
2787 res.push(true);
2788 res
2789 }
2790 _ => res,
2791 }
2792 }
2793
2794 fn extract_projection(&self, place: &Place<'tcx>, aggre: Aggre) -> ProjectionSupport<'tcx> {
2795 let mut prj: ProjectionSupport<'tcx> = ProjectionSupport::default();
2799 if aggre.is_some() {
2800 let ty = place.ty(&self.body.local_decls, self.tcx());
2805 prj.pf_vec.push((aggre.unwrap(), ty.ty));
2806 return prj;
2807 }
2808 for (idx, each_pj) in place.projection.iter().enumerate() {
2809 match each_pj {
2810 ProjectionElem::Field(field, ty) => {
2811 prj.pf_push(field.index(), ty);
2812 if prj.pf_vec.len() > 1 {
2813 prj.unsupport = true;
2814 break;
2815 }
2816 if prj.deref {
2817 prj.unsupport = true;
2818 break;
2819 }
2820 }
2821 ProjectionElem::Deref => {
2822 prj.deref = true;
2823 if idx > 0 {
2824 prj.unsupport = true;
2825 break;
2826 }
2827 }
2828 ProjectionElem::Downcast(.., ref vidx) => {
2829 prj.downcast = Some(*vidx);
2830 if idx > 0 {
2831 prj.unsupport = true;
2832 break;
2833 }
2834 }
2835 ProjectionElem::ConstantIndex { .. }
2836 | ProjectionElem::Subslice { .. }
2837 | ProjectionElem::Index(..)
2838 | ProjectionElem::OpaqueCast(..) => {
2839 prj.unsupport = true;
2840 break;
2841 }
2842 _ => todo!(),
2843 }
2844 }
2845 prj
2846 }
2847}
2848
2849fn new_local_name(local: usize, bidx: usize, sidx: usize) -> String {
2850 let s = bidx
2851 .to_string()
2852 .add("_")
2853 .add(&sidx.to_string())
2854 .add("_")
2855 .add(&local.to_string());
2856 s
2857}
2858
2859fn is_place_containing_ptr(ty: &Ty) -> bool {
2860 match ty.kind() {
2861 TyKind::Tuple(tuple_ty_list) => {
2862 for tuple_ty in tuple_ty_list.iter() {
2863 if tuple_ty.is_any_ptr() {
2864 return true;
2865 }
2866 }
2867 false
2868 }
2869 TyKind::RawPtr(..) => true,
2870 TyKind::Ref(..) => true,
2871 _ => false,
2872 }
2873}
2874
2875#[derive(Debug)]
2876struct ProjectionSupport<'tcx> {
2877 pf_vec: Vec<(usize, Ty<'tcx>)>,
2878 deref: bool,
2879 downcast: Disc,
2880 unsupport: bool,
2881}
2882
2883impl<'tcx> Default for ProjectionSupport<'tcx> {
2884 fn default() -> Self {
2885 Self {
2886 pf_vec: Vec::default(),
2887 deref: false,
2888 downcast: None,
2889 unsupport: false,
2890 }
2891 }
2892}
2893
2894impl<'tcx> ProjectionSupport<'tcx> {
2895 pub fn pf_push(&mut self, index: usize, ty: Ty<'tcx>) {
2896 self.pf_vec.push((index, ty));
2897 }
2898
2899 pub fn is_unsupported(&self) -> bool {
2900 self.unsupport == true
2901 }
2902
2903 pub fn has_field(&self) -> bool {
2904 self.pf_vec.len() > 0
2905 }
2906
2907 pub fn has_downcast(&self) -> bool {
2908 self.downcast.is_some()
2909 }
2910
2911 pub fn downcast(&self) -> Disc {
2912 self.downcast
2913 }
2914
2915 pub fn index_needed(&self) -> usize {
2916 self.pf_vec[0].0
2917 }
2918}
2919
2920fn has_projection(place: &Place) -> bool {
2921 return if place.projection.len() > 0 {
2922 true
2923 } else {
2924 false
2925 };
2926}
2927
2928fn heap_layout_to_rustbv(layout: &Vec<OwnedHeap>) -> Vec<bool> {
2929 let mut v = Vec::default();
2930 for item in layout.iter() {
2931 match item {
2932 OwnedHeap::Unknown => rap_error!("item of raw type owner is uninit"),
2933 OwnedHeap::False => v.push(false),
2934 OwnedHeap::True => v.push(true),
2935 }
2936 }
2937 v
2938}
2939
2940fn reverse_heap_layout_to_rustbv(layout: &Vec<OwnedHeap>) -> Vec<bool> {
2941 let mut v = Vec::default();
2942 for item in layout.iter() {
2943 match item {
2944 OwnedHeap::Unknown => rap_error!("item of raw type owner is uninit"),
2945 OwnedHeap::False => v.push(true),
2946 OwnedHeap::True => v.push(false),
2947 }
2948 }
2949 v
2950}
2951
2952fn rustbv_merge(a: &Vec<bool>, b: &Vec<bool>) -> Vec<bool> {
2953 assert_eq!(a.len(), b.len());
2954 let mut bv = Vec::new();
2955 for idx in 0..a.len() {
2956 bv.push(a[idx] || b[idx]);
2957 }
2958 bv
2959}
2960
2961fn rustbv_to_int(bv: &Vec<bool>) -> u64 {
2965 let mut ans = 0;
2966 let mut base = 1;
2967 for tf in bv.iter() {
2968 ans = ans + base * (*tf as u64);
2969 base = base * 2;
2970 }
2971 ans
2972}
2973
2974fn help_debug_goal_stmt<'tcx, 'ctx>(
2975 ctx: &'ctx z3::Context,
2976 goal: &'ctx z3::Goal<'ctx>,
2977 bidx: usize,
2978 sidx: usize,
2979) {
2980 let debug_name = format!("CONSTRAINTS: S {} {}", bidx, sidx);
2981 let dbg_bool = ast::Bool::new_const(ctx, debug_name);
2982 goal.assert(&dbg_bool);
2983}
2984
2985fn help_debug_goal_term<'tcx, 'ctx>(
2986 ctx: &'ctx z3::Context,
2987 goal: &'ctx z3::Goal<'ctx>,
2988 bidx: usize,
2989) {
2990 let debug_name = format!("CONSTRAINTS: T {}", bidx);
2991 let dbg_bool = ast::Bool::new_const(ctx, debug_name);
2992 goal.assert(&dbg_bool);
2993}