[clang][analyzer] Check for label location bindings in DereferenceChecker
(#91119)
Resolves #89264 Values should not be stored in addresses of labels, this throws a fatal error when this happens. --------- Co-authored-by: Balazs Benics <benicsbalazs@gmail.com>
This commit is contained in:
parent
99934daa9b
commit
efe91cf78b
@ -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;
|
||||
@ -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.
|
||||
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user