xref: /llvm-project/clang/test/Analysis/Checkers/WebKit/unchecked-local-vars.cpp (revision 61a6439f35b6de28ff4aff4450d6fca970292fd5)
1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedLocalVarsChecker -verify %s
2 
3 #include "mock-types.h"
4 #include "mock-system-header.h"
5 
6 void someFunction();
7 
8 namespace raw_ptr {
9 void foo() {
10   CheckedObj *bar;
11   // FIXME: later on we might warn on uninitialized vars too
12 }
13 
14 void bar(CheckedObj *) {}
15 } // namespace raw_ptr
16 
17 namespace reference {
18 void foo_ref() {
19   CheckedObj automatic;
20   CheckedObj &bar = automatic;
21   // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
22   someFunction();
23   bar.method();
24 }
25 
26 void foo_ref_trivial() {
27   CheckedObj automatic;
28   CheckedObj &bar = automatic;
29 }
30 
31 void bar_ref(CheckedObj &) {}
32 } // namespace reference
33 
34 namespace guardian_scopes {
35 void foo1() {
36   CheckedPtr<CheckedObj> foo;
37   { CheckedObj *bar = foo.get(); }
38 }
39 
40 void foo2() {
41   CheckedPtr<CheckedObj> foo;
42   // missing embedded scope here
43   CheckedObj *bar = foo.get();
44   // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
45   someFunction();
46   bar->method();
47 }
48 
49 void foo3() {
50   CheckedPtr<CheckedObj> foo;
51   {
52     { CheckedObj *bar = foo.get(); }
53   }
54 }
55 
56 void foo4() {
57   {
58     CheckedPtr<CheckedObj> foo;
59     { CheckedObj *bar = foo.get(); }
60   }
61 }
62 
63 void foo5() {
64   CheckedPtr<CheckedObj> foo;
65   auto* bar = foo.get();
66   bar->trivial();
67 }
68 
69 void foo6() {
70   CheckedPtr<CheckedObj> foo;
71   auto* bar = foo.get();
72   // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
73   bar->method();
74 }
75 
76 struct SelfReferencingStruct {
77   SelfReferencingStruct* ptr;
78   CheckedObj* obj { nullptr };
79 };
80 
81 void foo7(CheckedObj* obj) {
82   SelfReferencingStruct bar = { &bar, obj };
83   bar.obj->method();
84 }
85 
86 } // namespace guardian_scopes
87 
88 namespace auto_keyword {
89 class Foo {
90   CheckedObj *provide_ref_ctnbl();
91 
92   void evil_func() {
93     CheckedObj *bar = provide_ref_ctnbl();
94     // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
95     auto *baz = provide_ref_ctnbl();
96     // expected-warning@-1{{Local variable 'baz' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
97     auto *baz2 = this->provide_ref_ctnbl();
98     // expected-warning@-1{{Local variable 'baz2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
99     [[clang::suppress]] auto *baz_suppressed = provide_ref_ctnbl(); // no-warning
100   }
101 
102   void func() {
103     CheckedObj *bar = provide_ref_ctnbl();
104     // expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
105     if (bar)
106       bar->method();
107   }
108 };
109 } // namespace auto_keyword
110 
111 namespace guardian_casts {
112 void foo1() {
113   CheckedPtr<CheckedObj> foo;
114   {
115     CheckedObj *bar = downcast<CheckedObj>(foo.get());
116     bar->method();
117   }
118   foo->method();
119 }
120 
121 void foo2() {
122   CheckedPtr<CheckedObj> foo;
123   {
124     CheckedObj *bar =
125         static_cast<CheckedObj *>(downcast<CheckedObj>(foo.get()));
126     someFunction();
127   }
128 }
129 } // namespace guardian_casts
130 
131 namespace guardian_ref_conversion_operator {
132 void foo() {
133   CheckedRef<CheckedObj> rc;
134   {
135     CheckedObj &rr = rc;
136     rr.method();
137     someFunction();
138   }
139 }
140 } // namespace guardian_ref_conversion_operator
141 
142 namespace ignore_for_if {
143 CheckedObj *provide_ref_ctnbl() { return nullptr; }
144 
145 void foo() {
146   // no warnings
147   if (CheckedObj *a = provide_ref_ctnbl())
148     a->trivial();
149   for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;)
150     b->trivial();
151   CheckedObj *array[1];
152   for (CheckedObj *c : array)
153     c->trivial();
154   while (CheckedObj *d = provide_ref_ctnbl())
155     d->trivial();
156   do {
157     CheckedObj *e = provide_ref_ctnbl();
158     e->trivial();
159   } while (1);
160   someFunction();
161 }
162 
163 void bar() {
164   if (CheckedObj *a = provide_ref_ctnbl()) {
165     // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
166     a->method();
167   }
168   for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;) {
169     // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
170     b->method();
171   }
172   CheckedObj *array[1];
173   for (CheckedObj *c : array) {
174     // expected-warning@-1{{Local variable 'c' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
175     c->method();
176   }
177 
178   while (CheckedObj *d = provide_ref_ctnbl()) {
179     // expected-warning@-1{{Local variable 'd' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
180     d->method();
181   }
182   do {
183     CheckedObj *e = provide_ref_ctnbl();
184     // expected-warning@-1{{Local variable 'e' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
185     e->method();
186   } while (1);
187   someFunction();
188 }
189 
190 } // namespace ignore_for_if
191 
192 namespace ignore_system_headers {
193 
194 CheckedObj *provide_checkable();
195 
196 void system_header() {
197   localVar<CheckedObj>(provide_checkable);
198 }
199 
200 } // ignore_system_headers
201 
202 namespace conditional_op {
203 CheckedObj *provide_checkable();
204 bool bar();
205 
206 void foo() {
207   CheckedObj *a = bar() ? nullptr : provide_checkable();
208   // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
209   CheckedPtr<CheckedObj> b = provide_checkable();
210   {
211     CheckedObj* c = bar() ? nullptr : b.get();
212     c->method();
213     CheckedObj* d = bar() ? b.get() : nullptr;
214     d->method();
215   }
216 }
217 
218 } // namespace conditional_op
219 
220 namespace local_assignment_basic {
221 
222 CheckedObj *provide_checkable();
223 
224 void foo(CheckedObj* a) {
225   CheckedObj* b = a;
226   // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
227   if (b->trivial())
228     b = provide_checkable();
229 }
230 
231 void bar(CheckedObj* a) {
232   CheckedObj* b;
233   // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
234   b = provide_checkable();
235 }
236 
237 void baz() {
238   CheckedPtr a = provide_checkable();
239   {
240     CheckedObj* b = a.get();
241     // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
242     b = provide_checkable();
243   }
244 }
245 
246 } // namespace local_assignment_basic
247 
248 namespace local_assignment_to_parameter {
249 
250 CheckedObj *provide_checkable();
251 void someFunction();
252 
253 void foo(CheckedObj* a) {
254   a = provide_checkable();
255   // expected-warning@-1{{Assignment to an unchecked parameter 'a' is unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
256   someFunction();
257   a->method();
258 }
259 
260 } // namespace local_assignment_to_parameter
261 
262 namespace local_assignment_to_static_local {
263 
264 CheckedObj *provide_checkable();
265 void someFunction();
266 
267 void foo() {
268   static CheckedObj* a = nullptr;
269   // expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
270   a = provide_checkable();
271   someFunction();
272   a->method();
273 }
274 
275 } // namespace local_assignment_to_static_local
276 
277 namespace local_assignment_to_global {
278 
279 CheckedObj *provide_ref_cntbl();
280 void someFunction();
281 
282 CheckedObj* g_a = nullptr;
283 // expected-warning@-1{{Global variable 'local_assignment_to_global::g_a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
284 
285 void foo() {
286   g_a = provide_ref_cntbl();
287   someFunction();
288   g_a->method();
289 }
290 
291 } // namespace local_assignment_to_global
292 
293 namespace local_refcountable_checkable_object {
294 
295 RefCountableAndCheckable* provide_obj();
296 
297 void local_raw_ptr() {
298   RefCountableAndCheckable* a = nullptr;
299   // expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
300   a = provide_obj();
301   a->method();
302 }
303 
304 void local_checked_ptr() {
305   RefPtr<RefCountableAndCheckable> a = nullptr;
306   a = provide_obj();
307   a->method();
308 }
309 
310 void local_var_with_guardian_checked_ptr() {
311   RefPtr<RefCountableAndCheckable> a = provide_obj();
312   {
313     auto* b = a.get();
314     b->method();
315   }
316 }
317 
318 void local_var_with_guardian_checked_ptr_with_assignment() {
319   RefPtr<RefCountableAndCheckable> a = provide_obj();
320   {
321     RefCountableAndCheckable* b = a.get();
322     // expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
323     b = provide_obj();
324     b->method();
325   }
326 }
327 
328 void local_var_with_guardian_checked_ref() {
329   Ref<RefCountableAndCheckable> a = *provide_obj();
330   {
331     RefCountableAndCheckable& b = a;
332     b.method();
333   }
334 }
335 
336 void static_var() {
337   static RefCountableAndCheckable* a = nullptr;
338   // expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
339   a = provide_obj();
340 }
341 
342 } // namespace local_refcountable_checkable_object
343