Files
clang-p2996/clang/test/Analysis/Checkers/WebKit/unchecked-local-vars.cpp
Ryosuke Niwa 61a6439f35 Introduce a new WebKit checker for a unchecked local variable (#113708)
This PR introduces alpha.webkit.UncheckedLocalVarsChecker which detects
a raw reference or a raw pointer local, static, or global variable to a
CheckedPtr capable object without a guardian variable in an outer scope.
2024-10-31 23:53:07 -07:00

343 lines
8.4 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedLocalVarsChecker -verify %s
#include "mock-types.h"
#include "mock-system-header.h"
void someFunction();
namespace raw_ptr {
void foo() {
CheckedObj *bar;
// FIXME: later on we might warn on uninitialized vars too
}
void bar(CheckedObj *) {}
} // namespace raw_ptr
namespace reference {
void foo_ref() {
CheckedObj automatic;
CheckedObj &bar = automatic;
// expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
someFunction();
bar.method();
}
void foo_ref_trivial() {
CheckedObj automatic;
CheckedObj &bar = automatic;
}
void bar_ref(CheckedObj &) {}
} // namespace reference
namespace guardian_scopes {
void foo1() {
CheckedPtr<CheckedObj> foo;
{ CheckedObj *bar = foo.get(); }
}
void foo2() {
CheckedPtr<CheckedObj> foo;
// missing embedded scope here
CheckedObj *bar = foo.get();
// expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
someFunction();
bar->method();
}
void foo3() {
CheckedPtr<CheckedObj> foo;
{
{ CheckedObj *bar = foo.get(); }
}
}
void foo4() {
{
CheckedPtr<CheckedObj> foo;
{ CheckedObj *bar = foo.get(); }
}
}
void foo5() {
CheckedPtr<CheckedObj> foo;
auto* bar = foo.get();
bar->trivial();
}
void foo6() {
CheckedPtr<CheckedObj> foo;
auto* bar = foo.get();
// expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
bar->method();
}
struct SelfReferencingStruct {
SelfReferencingStruct* ptr;
CheckedObj* obj { nullptr };
};
void foo7(CheckedObj* obj) {
SelfReferencingStruct bar = { &bar, obj };
bar.obj->method();
}
} // namespace guardian_scopes
namespace auto_keyword {
class Foo {
CheckedObj *provide_ref_ctnbl();
void evil_func() {
CheckedObj *bar = provide_ref_ctnbl();
// expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
auto *baz = provide_ref_ctnbl();
// expected-warning@-1{{Local variable 'baz' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
auto *baz2 = this->provide_ref_ctnbl();
// expected-warning@-1{{Local variable 'baz2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
[[clang::suppress]] auto *baz_suppressed = provide_ref_ctnbl(); // no-warning
}
void func() {
CheckedObj *bar = provide_ref_ctnbl();
// expected-warning@-1{{Local variable 'bar' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
if (bar)
bar->method();
}
};
} // namespace auto_keyword
namespace guardian_casts {
void foo1() {
CheckedPtr<CheckedObj> foo;
{
CheckedObj *bar = downcast<CheckedObj>(foo.get());
bar->method();
}
foo->method();
}
void foo2() {
CheckedPtr<CheckedObj> foo;
{
CheckedObj *bar =
static_cast<CheckedObj *>(downcast<CheckedObj>(foo.get()));
someFunction();
}
}
} // namespace guardian_casts
namespace guardian_ref_conversion_operator {
void foo() {
CheckedRef<CheckedObj> rc;
{
CheckedObj &rr = rc;
rr.method();
someFunction();
}
}
} // namespace guardian_ref_conversion_operator
namespace ignore_for_if {
CheckedObj *provide_ref_ctnbl() { return nullptr; }
void foo() {
// no warnings
if (CheckedObj *a = provide_ref_ctnbl())
a->trivial();
for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;)
b->trivial();
CheckedObj *array[1];
for (CheckedObj *c : array)
c->trivial();
while (CheckedObj *d = provide_ref_ctnbl())
d->trivial();
do {
CheckedObj *e = provide_ref_ctnbl();
e->trivial();
} while (1);
someFunction();
}
void bar() {
if (CheckedObj *a = provide_ref_ctnbl()) {
// expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
a->method();
}
for (CheckedObj *b = provide_ref_ctnbl(); b != nullptr;) {
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
b->method();
}
CheckedObj *array[1];
for (CheckedObj *c : array) {
// expected-warning@-1{{Local variable 'c' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
c->method();
}
while (CheckedObj *d = provide_ref_ctnbl()) {
// expected-warning@-1{{Local variable 'd' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
d->method();
}
do {
CheckedObj *e = provide_ref_ctnbl();
// expected-warning@-1{{Local variable 'e' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
e->method();
} while (1);
someFunction();
}
} // namespace ignore_for_if
namespace ignore_system_headers {
CheckedObj *provide_checkable();
void system_header() {
localVar<CheckedObj>(provide_checkable);
}
} // ignore_system_headers
namespace conditional_op {
CheckedObj *provide_checkable();
bool bar();
void foo() {
CheckedObj *a = bar() ? nullptr : provide_checkable();
// expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
CheckedPtr<CheckedObj> b = provide_checkable();
{
CheckedObj* c = bar() ? nullptr : b.get();
c->method();
CheckedObj* d = bar() ? b.get() : nullptr;
d->method();
}
}
} // namespace conditional_op
namespace local_assignment_basic {
CheckedObj *provide_checkable();
void foo(CheckedObj* a) {
CheckedObj* b = a;
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
if (b->trivial())
b = provide_checkable();
}
void bar(CheckedObj* a) {
CheckedObj* b;
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
b = provide_checkable();
}
void baz() {
CheckedPtr a = provide_checkable();
{
CheckedObj* b = a.get();
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
b = provide_checkable();
}
}
} // namespace local_assignment_basic
namespace local_assignment_to_parameter {
CheckedObj *provide_checkable();
void someFunction();
void foo(CheckedObj* a) {
a = provide_checkable();
// expected-warning@-1{{Assignment to an unchecked parameter 'a' is unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
someFunction();
a->method();
}
} // namespace local_assignment_to_parameter
namespace local_assignment_to_static_local {
CheckedObj *provide_checkable();
void someFunction();
void foo() {
static CheckedObj* a = nullptr;
// expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
a = provide_checkable();
someFunction();
a->method();
}
} // namespace local_assignment_to_static_local
namespace local_assignment_to_global {
CheckedObj *provide_ref_cntbl();
void someFunction();
CheckedObj* g_a = nullptr;
// expected-warning@-1{{Global variable 'local_assignment_to_global::g_a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
void foo() {
g_a = provide_ref_cntbl();
someFunction();
g_a->method();
}
} // namespace local_assignment_to_global
namespace local_refcountable_checkable_object {
RefCountableAndCheckable* provide_obj();
void local_raw_ptr() {
RefCountableAndCheckable* a = nullptr;
// expected-warning@-1{{Local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
a = provide_obj();
a->method();
}
void local_checked_ptr() {
RefPtr<RefCountableAndCheckable> a = nullptr;
a = provide_obj();
a->method();
}
void local_var_with_guardian_checked_ptr() {
RefPtr<RefCountableAndCheckable> a = provide_obj();
{
auto* b = a.get();
b->method();
}
}
void local_var_with_guardian_checked_ptr_with_assignment() {
RefPtr<RefCountableAndCheckable> a = provide_obj();
{
RefCountableAndCheckable* b = a.get();
// expected-warning@-1{{Local variable 'b' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
b = provide_obj();
b->method();
}
}
void local_var_with_guardian_checked_ref() {
Ref<RefCountableAndCheckable> a = *provide_obj();
{
RefCountableAndCheckable& b = a;
b.method();
}
}
void static_var() {
static RefCountableAndCheckable* a = nullptr;
// expected-warning@-1{{Static local variable 'a' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}}
a = provide_obj();
}
} // namespace local_refcountable_checkable_object