1 //== ReturnStackAddressChecker.cpp ------------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines ReturnStackAddressChecker, which is a path-sensitive
11 // check which looks for the addresses of stack variables being returned to
14 //===----------------------------------------------------------------------===//
16 #include "GRExprEngineInternalChecks.h"
17 #include "clang/Checker/PathSensitive/GRExprEngine.h"
18 #include "clang/Checker/BugReporter/BugReporter.h"
19 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
20 #include "clang/Basic/SourceManager.h"
21 #include "llvm/ADT/SmallString.h"
23 using namespace clang;
26 class ReturnStackAddressChecker :
27 public CheckerVisitor<ReturnStackAddressChecker> {
30 ReturnStackAddressChecker() : BT(0) {}
31 static void *getTag();
32 void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
34 void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
38 void clang::RegisterReturnStackAddressChecker(GRExprEngine &Eng) {
39 Eng.registerCheck(new ReturnStackAddressChecker());
42 void *ReturnStackAddressChecker::getTag() {
43 static int x = 0; return &x;
46 void ReturnStackAddressChecker::EmitStackError(CheckerContext &C,
49 ExplodedNode *N = C.GenerateSink();
55 BT = new BuiltinBug("Return of address to stack-allocated memory");
57 // Generate a report for this bug.
58 llvm::SmallString<512> buf;
59 llvm::raw_svector_ostream os(buf);
62 // Get the base region, stripping away fields and elements.
63 R = R->getBaseRegion();
65 // Check if the region is a compound literal.
66 if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {
67 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
68 os << "Address of stack memory associated with a compound literal "
70 << C.getSourceManager().getInstantiationLineNumber(CL->getLocStart())
71 << " returned to caller";
72 range = CL->getSourceRange();
74 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
75 const Expr* ARE = AR->getExpr();
76 SourceLocation L = ARE->getLocStart();
77 range = ARE->getSourceRange();
78 os << "Address of stack memory allocated by call to alloca() on line "
79 << C.getSourceManager().getInstantiationLineNumber(L)
80 << " returned to caller";
82 else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
83 const BlockDecl *BD = BR->getCodeRegion()->getDecl();
84 SourceLocation L = BD->getLocStart();
85 range = BD->getSourceRange();
86 os << "Address of stack-allocated block declared on line "
87 << C.getSourceManager().getInstantiationLineNumber(L)
88 << " returned to caller";
90 else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
91 os << "Address of stack memory associated with local variable '"
92 << VR->getString() << "' returned";
93 range = VR->getDecl()->getSourceRange();
96 assert(false && "Invalid region in ReturnStackAddressChecker.");
100 RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
101 report->addRange(RetE->getSourceRange());
103 report->addRange(range);
105 C.EmitReport(report);
108 void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
109 const ReturnStmt *RS) {
111 const Expr *RetE = RS->getRetValue();
115 SVal V = C.getState()->getSVal(RetE);
116 const MemRegion *R = V.getAsRegion();
118 if (!R || !R->hasStackStorage())
121 if (R->hasStackStorage()) {
122 EmitStackError(C, R, RetE);