2009-11-04 09:43:07 +08:00
|
|
|
//=== VLASizeChecker.cpp - Undefined dereference checker --------*- C++ -*-===//
|
2009-11-03 20:13:38 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-11-04 09:43:07 +08:00
|
|
|
// This defines two VLASizeCheckers, a builtin check in GRExprEngine that
|
|
|
|
// performs checks for declaration of VLA of undefined or zero size.
|
2009-11-03 20:13:38 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-07 05:51:50 +08:00
|
|
|
#include "GRExprEngineInternalChecks.h"
|
|
|
|
#include "clang/Analysis/PathSensitive/Checker.h"
|
2009-11-03 20:13:38 +08:00
|
|
|
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
|
|
|
|
#include "clang/Analysis/PathSensitive/BugReporter.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2009-11-07 05:51:50 +08:00
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN UndefSizedVLAChecker : public Checker {
|
|
|
|
BugType *BT;
|
|
|
|
|
|
|
|
public:
|
|
|
|
UndefSizedVLAChecker() : BT(0) {}
|
|
|
|
static void *getTag();
|
|
|
|
ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
|
|
|
const GRState *state, Stmt *S, GRExprEngine &Eng);
|
|
|
|
};
|
|
|
|
|
|
|
|
class VISIBILITY_HIDDEN ZeroSizedVLAChecker : public Checker {
|
|
|
|
BugType *BT;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ZeroSizedVLAChecker() : BT(0) {}
|
|
|
|
static void *getTag();
|
|
|
|
ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
|
|
|
|
const GRState *state, Stmt *S, GRExprEngine &Eng);
|
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
|
|
|
|
Eng.registerCheck(new UndefSizedVLAChecker());
|
|
|
|
Eng.registerCheck(new ZeroSizedVLAChecker());
|
|
|
|
}
|
|
|
|
|
2009-11-04 09:43:07 +08:00
|
|
|
void *UndefSizedVLAChecker::getTag() {
|
|
|
|
static int x = 0;
|
|
|
|
return &x;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
|
|
|
|
const GRState *state,
|
|
|
|
Stmt *S, GRExprEngine &Eng) {
|
|
|
|
GRStmtNodeBuilder &Builder = Eng.getBuilder();
|
|
|
|
BugReporter &BR = Eng.getBugReporter();
|
|
|
|
|
|
|
|
if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
|
|
|
|
// FIXME: Handle multi-dimensional VLAs.
|
|
|
|
Expr* SE = VLA->getSizeExpr();
|
|
|
|
SVal Size_untested = state->getSVal(SE);
|
|
|
|
|
|
|
|
if (Size_untested.isUndef()) {
|
|
|
|
if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
|
|
|
|
N->markAsSink();
|
|
|
|
if (!BT)
|
2009-11-06 08:44:32 +08:00
|
|
|
BT = new BuiltinBug("Declared variable-length array (VLA) uses a "
|
|
|
|
"garbage value as its size");
|
2009-11-04 09:43:07 +08:00
|
|
|
|
|
|
|
EnhancedBugReport *R =
|
|
|
|
new EnhancedBugReport(*BT, BT->getName().c_str(), N);
|
|
|
|
R->addRange(SE->getSourceRange());
|
|
|
|
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
|
|
|
|
BR.EmitReport(R);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Pred;
|
|
|
|
}
|
|
|
|
|
2009-11-03 20:13:38 +08:00
|
|
|
void *ZeroSizedVLAChecker::getTag() {
|
|
|
|
static int x;
|
|
|
|
return &x;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
|
|
|
|
const GRState *state, Stmt *S,
|
|
|
|
GRExprEngine &Eng) {
|
|
|
|
GRStmtNodeBuilder &Builder = Eng.getBuilder();
|
|
|
|
BugReporter &BR = Eng.getBugReporter();
|
|
|
|
|
|
|
|
if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
|
|
|
|
// FIXME: Handle multi-dimensional VLAs.
|
|
|
|
Expr* SE = VLA->getSizeExpr();
|
|
|
|
SVal Size_untested = state->getSVal(SE);
|
|
|
|
|
|
|
|
DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
|
|
|
|
// Undefined size is checked in another checker.
|
|
|
|
if (!Size)
|
|
|
|
return Pred;
|
|
|
|
|
|
|
|
const GRState *zeroState = state->Assume(*Size, false);
|
|
|
|
state = state->Assume(*Size, true);
|
|
|
|
|
|
|
|
if (zeroState && !state) {
|
|
|
|
if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
|
|
|
|
N->markAsSink();
|
|
|
|
if (!BT)
|
2009-11-05 16:30:12 +08:00
|
|
|
BT = new BugType("Declared variable-length array (VLA) has zero size",
|
2009-11-03 20:13:38 +08:00
|
|
|
"Logic error");
|
|
|
|
|
|
|
|
EnhancedBugReport *R =
|
|
|
|
new EnhancedBugReport(*BT, BT->getName().c_str(), N);
|
|
|
|
R->addRange(SE->getSourceRange());
|
|
|
|
R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
|
|
|
|
BR.EmitReport(R);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!state)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Builder.generateNode(S, state, Pred);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return Pred;
|
|
|
|
}
|
2009-11-04 09:43:07 +08:00
|
|
|
|