Skip to main content

rapx/check/opt/data_collection/initialization/
vec_init.rs

1use annotate_snippets::Level;
2
3use rustc_middle::ty::TyCtxt;
4use rustc_span::Span;
5
6use crate::{
7    analysis::dataflow::*,
8    check::opt::OptCheck,
9};
10
11use crate::check::opt::report::OptReport;
12
13crate::def_paths! {
14    vec_from_elem: "std::vec::from_elem",
15}
16
17pub struct VecInitCheck {
18    record: Vec<Span>,
19}
20
21impl OptCheck for VecInitCheck {
22    fn new() -> Self {
23        Self { record: Vec::new() }
24    }
25
26    fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
27        let def_paths = &DEFPATHS.get_or_init(|| DefPaths::new(tcx));
28        for node in graph.nodes.iter() {
29            for op in node.ops.iter() {
30                if let NodeOp::Call(def_id) = op {
31                    if *def_id == def_paths.vec_from_elem.last_def_id() {
32                        self.record.push(node.span);
33                    }
34                }
35            }
36        }
37    }
38
39    fn report(&self, graph: &Graph) {
40        for span in self.record.iter() {
41            report_vec_init(graph, *span);
42        }
43    }
44
45    fn cnt(&self) -> usize {
46        self.record.len()
47    }
48}
49
50fn report_vec_init(graph: &Graph, span: Span) {
51    OptReport::from_graph(graph)
52        .file_name(span)
53        .title("Unnecessary data collection initialization detected")
54        .annotate(Level::Error, span, "Initialization happens here")
55        .footer("Use unsafe APIs to skip initialization.")
56        .emit();
57}