Skip to main content

rapx/check/opt/checking/bounds_checking/
bounds_extend.rs

1use once_cell::sync::OnceCell;
2
3use rustc_middle::ty::TyCtxt;
4use rustc_span::Span;
5
6use crate::{analysis::dataflow::*, helpers::def_path::DefPath};
7use annotate_snippets::Level;
8
9use crate::check::opt::check_utils::node_matches_call;
10use crate::check::opt::report::OptReport;
11
12use super::super::super::LEVEL;
13use super::super::super::NO_STD;
14use crate::check::opt::OptCheck;
15static DEFPATHS: OnceCell<DefPaths> = OnceCell::new();
16
17struct DefPaths {
18    vec_extend_from_slice: DefPath,
19}
20
21impl DefPaths {
22    pub fn new(tcx: &TyCtxt<'_>) -> Self {
23        let no_std = NO_STD.lock().unwrap();
24        if *no_std {
25            Self {
26                vec_extend_from_slice: DefPath::new("alloc::vec::Vec::extend_from_slice", tcx),
27            }
28        } else {
29            Self {
30                vec_extend_from_slice: DefPath::new("std::vec::Vec::extend_from_slice", tcx),
31            }
32        }
33    }
34}
35
36pub struct BoundsExtendCheck {
37    pub record: Vec<Span>,
38}
39
40impl OptCheck for BoundsExtendCheck {
41    fn new() -> Self {
42        Self { record: Vec::new() }
43    }
44
45    fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
46        let level = LEVEL.lock().unwrap();
47        if *level <= 1 {
48            return;
49        }
50        let def_paths = &DEFPATHS.get_or_init(|| DefPaths::new(tcx));
51        for node in graph.nodes.iter() {
52            if node_matches_call(node, &[def_paths.vec_extend_from_slice.last_def_id()]) {
53                self.record.push(node.span);
54            }
55        }
56    }
57
58    fn report(&self, graph: &Graph) {
59        for span in self.record.iter() {
60            report_extend_bug(graph, *span);
61        }
62    }
63
64    fn cnt(&self) -> usize {
65        self.record.len()
66    }
67}
68
69fn report_extend_bug(graph: &Graph, span: Span) {
70    OptReport::from_graph(graph)
71        .title("Unnecessary bound checkings detected")
72        .annotate(Level::Error, span, "Checked here.")
73        .footer("Manipulate memory directly.")
74        .emit();
75}