Skip to content

Commit

Permalink
[clang][analyzer] Check for label location bindings in `DereferenceCh…
Browse files Browse the repository at this point in the history
…ecker` (llvm#91119)

Resolves llvm#89264

Values should not be stored in addresses of labels, this throws a fatal
error when this happens.

---------

Co-authored-by: Balazs Benics <[email protected]>
  • Loading branch information
Rajveer100 and steakhal authored May 13, 2024
1 parent 99934da commit efe91cf
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
15 changes: 14 additions & 1 deletion clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ class DereferenceChecker
: public Checker< check::Location,
check::Bind,
EventDispatcher<ImplicitNullDerefEvent> > {
enum DerefKind { NullPointer, UndefinedPointerValue };
enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel };

BugType BT_Null{this, "Dereference of null pointer", categories::LogicError};
BugType BT_Undef{this, "Dereference of undefined pointer value",
categories::LogicError};
BugType BT_Label{this, "Dereference of the address of a label",
categories::LogicError};

void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S,
CheckerContext &C) const;
Expand Down Expand Up @@ -167,6 +169,11 @@ void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State,
DerefStr1 = " results in an undefined pointer dereference";
DerefStr2 = " results in a dereference of an undefined pointer value";
break;
case DerefKind::AddressOfLabel:
BT = &BT_Label;
DerefStr1 = " results in an undefined pointer dereference";
DerefStr2 = " results in a dereference of an address of a label";
break;
};

// Generate an error node.
Expand Down Expand Up @@ -287,6 +294,12 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
if (V.isUndef())
return;

// One should never write to label addresses.
if (auto Label = L.getAs<loc::GotoLabel>()) {
reportBug(DerefKind::AddressOfLabel, C.getState(), S, C);
return;
}

const MemRegion *MR = L.getAsRegion();
const TypedValueRegion *TVR = dyn_cast_or_null<TypedValueRegion>(MR);
if (!TVR)
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) {
// Pointer arithmetic: '*(x + 2)' -> 'x') etc.
if (const Expr *Inner = peelOffPointerArithmetic(B)) {
E = Inner;
} else if (B->isAssignmentOp()) {
// Follow LHS of assignments: '*p = 404' -> 'p'.
E = B->getLHS();
} else {
// Probably more arithmetic can be pattern-matched here,
// but for now give up.
Expand Down
15 changes: 7 additions & 8 deletions clang/test/Analysis/gh-issue-89185.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-output text -verify %s

void clang_analyzer_dump(char);
void clang_analyzer_dump_ptr(char*);
void clang_analyzer_warnIfReached(void);

// https://github.com/llvm/llvm-project/issues/89185
void binding_to_label_loc() {
char *b = &&MyLabel;
char *b = &&MyLabel; // expected-note {{'b' initialized here}}
MyLabel:
*b = 0; // no-crash
clang_analyzer_dump_ptr(b); // expected-warning {{&&MyLabel}}
clang_analyzer_dump(*b); // expected-warning {{Unknown}}
// FIXME: We should never reach here, as storing to a label is invalid.
*b = 0;
// expected-warning@-1 {{Dereference of the address of a label}}
// expected-note@-2 {{Dereference of the address of a label}}
clang_analyzer_warnIfReached(); // no-warning: Unreachable due to fatal error.
}

0 comments on commit efe91cf

Please sign in to comment.