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