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