Skip to main content

rapx/check/opt/data_collection/suboptimal/
vec_remove.rs

1use annotate_snippets::Level;
2
3use crate::{analysis::dataflow::*, check::opt::OptCheck};
4use rustc_middle::ty::TyCtxt;
5use rustc_span::Span;
6
7use crate::check::opt::check_utils::node_matches_call;
8use crate::check::opt::report::OptReport;
9
10crate::def_paths! {
11    vec_remove: "std::vec::Vec::remove",
12    vec_insert: "std::vec::Vec::insert",
13}
14
15pub struct VecRemoveCheck {
16    record: Vec<Span>,
17}
18
19fn is_0_usize(node: &GraphNode) -> bool {
20    for op in node.ops.iter() {
21        if let NodeOp::Const(desc, _) = op {
22            if desc.eq("0_usize") {
23                return true;
24            }
25        }
26    }
27    false
28}
29
30impl OptCheck for VecRemoveCheck {
31    fn new() -> Self {
32        Self { record: vec![] }
33    }
34
35    fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
36        let def_paths = &DEFPATHS.get_or_init(|| DefPaths::new(tcx));
37        for node in graph.nodes.iter() {
38            if node_matches_call(
39                node,
40                &[
41                    def_paths.vec_remove.last_def_id(),
42                    def_paths.vec_insert.last_def_id(),
43                ],
44            ) {
45                let index_edge = &graph.edges[node.in_edges[1]];
46                let index_node = &graph.nodes[index_edge.src];
47                if is_0_usize(index_node) {
48                    self.record.push(node.span);
49                }
50            }
51        }
52    }
53
54    fn report(&self, graph: &Graph) {
55        for span in self.record.iter() {
56            report_vec_remove_bug(graph, *span);
57        }
58    }
59
60    fn cnt(&self) -> usize {
61        self.record.len()
62    }
63}
64
65fn report_vec_remove_bug(graph: &Graph, span: Span) {
66    OptReport::from_graph(graph)
67        .title("Improper data collection detected")
68        .annotate(
69            Level::Error,
70            span,
71            "Vec increasement / decreasement happens here.",
72        )
73        .footer("Use VecQueue instead of Vec.")
74        .emit();
75}