rapx/check/opt/checking/
encoding_checking.rs1pub mod array_encoding;
2pub mod string_lowercase;
3pub mod string_push;
4pub mod vec_encoding;
5
6use crate::{analysis::dataflow::*, check::opt::OptCheck};
7
8use annotate_snippets::Level;
9
10use crate::check::opt::report::OptReport;
11
12use rustc_middle::{mir::Local, ty::TyCtxt};
13use rustc_span::Span;
14
15use array_encoding::ArrayEncodingCheck;
16use string_lowercase::StringLowercaseCheck;
17use string_push::StringPushCheck;
18use vec_encoding::VecEncodingCheck;
19
20pub struct EncodingCheck {
21 vec_encoding: VecEncodingCheck,
22 array_encoding: ArrayEncodingCheck,
23 string_push: StringPushCheck,
24 string_lowercase: StringLowercaseCheck,
25}
26
27impl OptCheck for EncodingCheck {
28 fn new() -> Self {
29 Self {
30 vec_encoding: VecEncodingCheck::new(),
31 array_encoding: ArrayEncodingCheck::new(),
32 string_push: StringPushCheck::new(),
33 string_lowercase: StringLowercaseCheck::new(),
34 }
35 }
36
37 fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
38 self.vec_encoding.check(graph, tcx);
39 self.array_encoding.check(graph, tcx);
40 self.string_push.check(graph, tcx);
41 self.string_lowercase.check(graph, tcx);
42 }
43
44 fn report(&self, graph: &Graph) {
45 self.vec_encoding.report(graph);
46 self.array_encoding.report(graph);
47 self.string_push.report(graph);
48 self.string_lowercase.report(graph);
49 }
50
51 fn cnt(&self) -> usize {
52 self.vec_encoding.cnt()
53 + self.array_encoding.cnt()
54 + self.string_lowercase.cnt()
55 + self.string_push.cnt()
56 }
57}
58
59fn report_encoding_bug(graph: &Graph, span: Span) {
60 OptReport::from_graph(graph)
61 .title("Unnecessary encoding checkings detected")
62 .annotate(Level::Error, span, "Checked here.")
63 .footer("Use unsafe APIs.")
64 .emit();
65}
66
67fn value_is_from_const(graph: &Graph, value_idx: Local) -> bool {
68 let mut edge_validator = |graph: &Graph, idx: EdgeIdx| {
69 let edge = &graph.edges[idx];
70 let dst_node = &graph.nodes[edge.dst];
71 let same_seq_edge_cnt = dst_node
72 .in_edges
73 .iter()
74 .filter(|edge_idx| graph.edges[**edge_idx].seq == edge.seq)
75 .count();
76 match same_seq_edge_cnt {
77 1 => Graph::always_true_edge_validator(graph, idx),
78 2 => {
79 if let EdgeOp::Index = edge.op {
80 DFSStatus::Continue
81 } else {
82 DFSStatus::Stop
83 }
84 }
85 _ => DFSStatus::Stop,
86 }
87 };
88 graph
89 .find_first_node(
90 value_idx,
91 Direction::Upside,
92 &mut |graph: &Graph, idx: Local| {
93 let node = &graph.nodes[idx];
94 node.ops.iter().any(|op| {
95 if let NodeOp::Const(_, src_ty) = op {
96 src_ty.contains("u8")
97 } else {
98 false
99 }
100 })
101 },
102 &mut edge_validator,
103 )
104 .is_some()
105}