rapx/analysis/safedrop/
bug_records.rs1use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2use rustc_span::Span;
3
4use crate::rap_warn;
5use crate::utils::log::are_spans_in_same_file;
6use rustc_span::symbol::Symbol;
7
8use annotate_snippets::Level;
9use annotate_snippets::Renderer;
10use annotate_snippets::Snippet;
11
12use crate::utils::log::{
13 relative_pos_range, span_to_filename, span_to_line_number, span_to_source_code,
14};
15
16pub struct BugRecords {
17 pub df_bugs: FxHashMap<usize, Span>,
18 pub df_bugs_unwind: FxHashMap<usize, Span>,
19 pub uaf_bugs: FxHashSet<Span>,
20 pub dp_bugs: FxHashSet<Span>,
21 pub dp_bugs_unwind: FxHashSet<Span>,
22}
23
24impl BugRecords {
25 pub fn new() -> BugRecords {
26 BugRecords {
27 df_bugs: FxHashMap::default(),
28 df_bugs_unwind: FxHashMap::default(),
29 uaf_bugs: FxHashSet::default(),
30 dp_bugs: FxHashSet::default(),
31 dp_bugs_unwind: FxHashSet::default(),
32 }
33 }
34
35 pub fn is_bug_free(&self) -> bool {
36 self.df_bugs.is_empty()
37 && self.uaf_bugs.is_empty()
38 && self.dp_bugs.is_empty()
39 && self.dp_bugs_unwind.is_empty()
40 }
41
42 pub fn df_bugs_output(&self, fn_name: Symbol, span: Span) {
43 if !self.df_bugs.is_empty() {
44 rap_warn!("Double free detected in function {:}", fn_name);
45 let code_source = span_to_source_code(span);
46 let filename = span_to_filename(span);
47 let mut snippet = Snippet::source(&code_source)
48 .line_start(span_to_line_number(span))
49 .origin(&filename)
50 .fold(false);
51 for i in self.df_bugs.iter() {
52 if are_spans_in_same_file(span, *i.1) {
54 snippet = snippet.annotation(
55 Level::Warning
56 .span(relative_pos_range(span, *i.1))
57 .label("Double free detected."),
58 );
59 }
60 }
61 let message = Level::Warning
62 .title("Double free detected.")
63 .snippet(snippet);
64 let renderer = Renderer::styled();
65 println!("{}", renderer.render(message));
66 }
67 }
68
69 pub fn uaf_bugs_output(&self, fn_name: Symbol, span: Span) {
70 if !self.uaf_bugs.is_empty() {
71 rap_warn!("Use after free detected in function {:?}", fn_name);
72 let code_source = span_to_source_code(span);
73 let filename = span_to_filename(span);
74 let mut snippet = Snippet::source(&code_source)
75 .line_start(span_to_line_number(span))
76 .origin(&filename)
77 .fold(true);
78 for i in self.uaf_bugs.iter() {
79 if are_spans_in_same_file(span, *i) {
81 snippet = snippet.annotation(
82 Level::Warning
83 .span(relative_pos_range(span, *i))
84 .label("Use after free detected."),
85 );
86 }
87 }
88 let message = Level::Warning
89 .title("Use after free detected.")
90 .snippet(snippet);
91 let renderer = Renderer::styled();
92 println!("{}", renderer.render(message));
93 }
94 }
95
96 pub fn dp_bug_output(&self, fn_name: Symbol, span: Span) {
97 let code_source = span_to_source_code(span);
98 let filename = span_to_filename(span);
99 if !self.dp_bugs.is_empty() {
100 rap_warn!("Dangling pointer detected in function {:?}", fn_name);
101 let mut snippet = Snippet::source(&code_source)
102 .line_start(span_to_line_number(span))
103 .origin(&filename)
104 .fold(false);
105 for i in self.dp_bugs.iter() {
106 if are_spans_in_same_file(span, *i) {
108 snippet = snippet.annotation(
109 Level::Warning
110 .span(relative_pos_range(span, *i))
111 .label("Dangling pointer detected."),
112 );
113 }
114 }
115 let message = Level::Warning
116 .title("Dangling pointer detected.")
117 .snippet(snippet);
118 let renderer = Renderer::styled();
119 println!("{}", renderer.render(message));
120 }
121 if !self.dp_bugs_unwind.is_empty() {
122 rap_warn!(
123 "Dangling pointer detected in function {:?} during unwinding.",
124 fn_name
125 );
126 let mut snippet = Snippet::source(&code_source)
127 .line_start(span_to_line_number(span))
128 .origin(&filename)
129 .fold(false);
130 for i in self.dp_bugs_unwind.iter() {
131 if are_spans_in_same_file(span, *i) {
133 snippet = snippet.annotation(
134 Level::Warning
135 .span(relative_pos_range(span, *i))
136 .label("Dangling pointer detected during unwinding."),
137 );
138 }
139 }
140 let message = Level::Warning
141 .title("Dangling pointer detected during unwinding.")
142 .snippet(snippet);
143 let renderer = Renderer::styled();
144 println!("{}", renderer.render(message));
145 }
146 }
147}