"Have you added a test to make sure that is the case? (If yes, what's the
function name. I could not easily find it.) It would be similar to the
path-sensitive check you've added but the check against '0' would be done in an
inlined function."
Done, 'void testMallocIdc(int i)' added.
"Looks like you've removed the checks from the unix checker along with the
tests. Can you add the tests back? I suggest adding your checker to the test
file that contains the existing tests and check that it produces the same exact
output."
Done.
"char *foo = realloc(ptr, 0); // TODO:expected-warning{{Call to 'realloc()' has
an allocation size of 0 bytes}}
Why should we warn in this case? It is possible that someone is trying to free
the memory by calling "realloc(ptr, 0)"
It is unsafe to use the value returned from an allocation function that was
asked for a zero-allocation ( C11 n1570, 7.22.3.1 ).
I changed the checkers behavior to those we've discussed above:
1. if the returned value of realloc(p, 0) is not assigned then silently treat
it as simple 'free' (the old behavior of unix.Malloc)
2. if the returned value is assigned then fire '0 size allocation' warning as
the usage of the returned pointer is not safe.
Additional changes in the new patch:
- renamed 'BasicAllocationCheck' to 'ZeroAllocationCheck' (MallocChecker.cpp)
- cut old zero-allocation tests that depended on the memory returned from
zero-realloc:
- reallocSizeZero1(), reallocSizeZero2() - tested specific case when we try to
free memory that was already freed by zero-realloc, in the case when
reallocation failed.
- reallocSizeZero3, reallocSizeZero4, reallocSizeZero5 - tested that we don't
track memory returned from zero-allocated realloc().
If the patch gets in as is all this tests will produce 'zero-size allocation
warning' at the point 'char *r = realloc(p, 0);'
There is no need to modify an old code that handles 'realloc', all the code is
still in use. Nothing special is done to stop tracking memory returned from
zero-realloc, in case of zero-realloc we just return from the function that
handles 'realloc' (MallocChecker::ReallocMem()) before the code that allocates
memory and processes the return value.
http://reviews.llvm.org/D6178
Files:
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
test/Analysis/malloc-annotations.c
test/Analysis/malloc.c
test/Analysis/unix-fns.c
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -160,10 +160,11 @@
{
public:
MallocChecker()
- : II_malloc(nullptr), II_free(nullptr), II_realloc(nullptr),
- II_calloc(nullptr), II_valloc(nullptr), II_reallocf(nullptr),
- II_strndup(nullptr), II_strdup(nullptr), II_kmalloc(nullptr),
- II_if_nameindex(nullptr), II_if_freenameindex(nullptr) {}
+ : II_alloca(nullptr), II_alloca_builtin(nullptr), II_malloc(nullptr),
+ II_free(nullptr), II_realloc(nullptr), II_calloc(nullptr),
+ II_valloc(nullptr), II_reallocf(nullptr), II_strndup(nullptr),
+ II_strdup(nullptr), II_kmalloc(nullptr), II_if_nameindex(nullptr),
+ II_if_freenameindex(nullptr) {}
/// In pessimistic mode, the checker assumes that it does not know which
/// functions might free the memory.
@@ -218,9 +219,11 @@
mutable std::unique_ptr<BugType> BT_BadFree[CK_NumCheckKinds];
mutable std::unique_ptr<BugType> BT_MismatchedDealloc;
mutable std::unique_ptr<BugType> BT_OffsetFree[CK_NumCheckKinds];
- mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
- *II_valloc, *II_reallocf, *II_strndup, *II_strdup,
- *II_kmalloc, *II_if_nameindex, *II_if_freenameindex;
+ mutable std::unique_ptr<BugType> BT_ZerroAllocation[CK_NumCheckKinds];
+ mutable IdentifierInfo *II_alloca, *II_alloca_builtin, *II_malloc, *II_free,
+ *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
+ *II_strndup, *II_strdup, *II_kmalloc, *II_if_nameindex,
+ *II_if_freenameindex;
mutable Optional<uint64_t> KernelZeroFlagVal;
void initIdentifierInfo(ASTContext &C) const;
@@ -252,22 +255,24 @@
MemoryOperationKind MemKind) const;
bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const;
///@}
+
+ /// \brief Perform a zero-allocation check.
+ ProgramStateRef ZeroAllocationCheck(CheckerContext &C, const CallExpr *CE,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const;
+
ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
const CallExpr *CE,
- const OwnershipAttr* Att) const;
+ const OwnershipAttr* Att,
+ ProgramStateRef State) const;
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- const Expr *SizeEx, SVal Init,
- ProgramStateRef State,
- AllocationFamily Family = AF_Malloc) {
- return MallocMemAux(C, CE,
- State->getSVal(SizeEx, C.getLocationContext()),
- Init, State, Family);
- }
-
+ const Expr *SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family = AF_Malloc);
static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
- SVal SizeEx, SVal Init,
- ProgramStateRef State,
- AllocationFamily Family = AF_Malloc);
+ SVal SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family = AF_Malloc);
// Check if this malloc() for special flags. At present that means M_ZERO or
// __GFP_ZERO (in which case, treat it like calloc).
@@ -281,7 +286,8 @@
AllocationFamily Family = AF_Malloc);
ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
- const OwnershipAttr* Att) const;
+ const OwnershipAttr* Att,
+ ProgramStateRef State) const;
ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
ProgramStateRef state, unsigned Num,
bool Hold,
@@ -295,8 +301,10 @@
bool ReturnsNullOnFailure = false) const;
ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
- bool FreesMemOnFailure) const;
- static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
+ bool FreesMemOnFailure,
+ ProgramStateRef State) const;
+ static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE,
+ ProgramStateRef State);
///\brief Check if the memory associated with this symbol was released.
bool isReleased(SymbolRef Sym, CheckerContext &C) const;
@@ -337,6 +345,8 @@
///@}
static bool SummarizeValue(raw_ostream &os, SVal V);
static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
+ void ReportZeroByteAllocation(CheckerContext &C, ProgramStateRef FalseState,
+ const Expr *Arg, const Expr *AllocExpr) const;
void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
const Expr *DeallocExpr) const;
void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,
@@ -497,6 +507,8 @@
void MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
if (II_malloc)
return;
+ II_alloca = &Ctx.Idents.get("alloca");
+ II_alloca_builtin = &Ctx.Idents.get("__builtin_alloca");
II_malloc = &Ctx.Idents.get("malloc");
II_free = &Ctx.Idents.get("free");
II_realloc = &Ctx.Idents.get("realloc");
@@ -545,9 +557,10 @@
}
if (Family == AF_Malloc && CheckAlloc) {
- if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
- FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
- FunI == II_strndup || FunI == II_kmalloc)
+ if (FunI == II_alloca || FunI == II_alloca_builtin || FunI == II_malloc ||
+ FunI == II_realloc || FunI == II_reallocf || FunI == II_calloc ||
+ FunI == II_valloc || FunI == II_strdup || FunI == II_strndup ||
+ FunI == II_kmalloc)
return true;
}
@@ -710,6 +723,9 @@
if (FunI == II_malloc) {
if (CE->getNumArgs() < 1)
return;
+ else if (CE->getNumArgs() == 1)
+ State = ZeroAllocationCheck(C, CE, 0, State);
+
if (CE->getNumArgs() < 3) {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
} else if (CE->getNumArgs() == 3) {
@@ -731,20 +747,30 @@
if (CE->getNumArgs() < 1)
return;
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
+ State = ZeroAllocationCheck(C, CE, 0, State);
} else if (FunI == II_realloc) {
- State = ReallocMem(C, CE, false);
+ State = ReallocMem(C, CE, false, State);
+ ParentMap &PM = C.getLocationContext()->getParentMap();
+ if (PM.isConsumedExpr(CE))
+ State = ZeroAllocationCheck(C, CE, 1, State);
} else if (FunI == II_reallocf) {
- State = ReallocMem(C, CE, true);
+ State = ReallocMem(C, CE, true, State);
+ ParentMap &PM = C.getLocationContext()->getParentMap();
+ if (PM.isConsumedExpr(CE))
+ State = ZeroAllocationCheck(C, CE, 1, State);
} else if (FunI == II_calloc) {
- State = CallocMem(C, CE);
+ State = CallocMem(C, CE, State);
+ State = ZeroAllocationCheck(C, CE, 0, State);
+ State = ZeroAllocationCheck(C, CE, 1, State);
} else if (FunI == II_free) {
State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
} else if (FunI == II_strdup) {
State = MallocUpdateRefState(C, CE, State);
} else if (FunI == II_strndup) {
State = MallocUpdateRefState(C, CE, State);
- }
- else if (isStandardNewDelete(FD, C.getASTContext())) {
+ } else if (FunI == II_alloca || FunI == II_alloca_builtin) {
+ State = ZeroAllocationCheck(C, CE, 0, State);
+ } else if (isStandardNewDelete(FD, C.getASTContext())) {
// Process direct calls to operator new/new[]/delete/delete[] functions
// as distinct from new/new[]/delete/delete[] expressions that are
// processed by the checkPostStmt callbacks for CXXNewExpr and
@@ -778,18 +804,53 @@
for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
switch (I->getOwnKind()) {
case OwnershipAttr::Returns:
- State = MallocMemReturnsAttr(C, CE, I);
+ State = MallocMemReturnsAttr(C, CE, I, State);
break;
case OwnershipAttr::Takes:
case OwnershipAttr::Holds:
- State = FreeMemAttr(C, CE, I);
+ State = FreeMemAttr(C, CE, I, State);
break;
}
}
}
C.addTransition(State);
}
+// Performs a 0-sized allocations check.
+ProgramStateRef MallocChecker::ZeroAllocationCheck(CheckerContext &C,
+ const CallExpr *CE,
+ const unsigned AllocationSizeArg,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
+ const Expr *Arg = CE->getArg(AllocationSizeArg);
+
+ Optional<DefinedSVal> DefArgVal =
+ State->getSVal(Arg, C.getLocationContext()).getAs<DefinedSVal>();
+
+ if (!DefArgVal)
+ return State;
+
+ // Check if the allocation size is 0.
+ ProgramStateRef TrueState, FalseState;
+ SValBuilder &SvalBuilder = C.getSValBuilder();
+ DefinedSVal Zero =
+ SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
+
+ std::tie(TrueState, FalseState) =
+ State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
+
+ if (TrueState && !FalseState) {
+ ReportZeroByteAllocation(C, FalseState, Arg, CE);
+ return nullptr;
+ }
+
+ // Assume the value is non-zero going forward.
+ assert(FalseState);
+ return FalseState;
+}
+
static QualType getDeepPointeeType(QualType T) {
QualType Result = T, PointeeType = T->getPointeeType();
while (!PointeeType.isNull()) {
@@ -919,22 +980,40 @@
ProgramStateRef
MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
- const OwnershipAttr *Att) const {
+ const OwnershipAttr *Att,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (Att->getModule() != II_malloc)
return nullptr;
OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
if (I != E) {
- return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+ return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State);
}
- return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
+ return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
+}
+
+ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
+ const CallExpr *CE,
+ const Expr *SizeEx, SVal Init,
+ ProgramStateRef State,
+ AllocationFamily Family) {
+ if (!State)
+ return nullptr;
+
+ return MallocMemAux(C, CE, State->getSVal(SizeEx, C.getLocationContext()),
+ Init, State, Family);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE,
SVal Size, SVal Init,
ProgramStateRef State,
AllocationFamily Family) {
+ if (!State)
+ return nullptr;
// We expect the malloc functions to return a pointer.
if (!Loc::isLocType(CE->getType()))
@@ -976,6 +1055,9 @@
const Expr *E,
ProgramStateRef State,
AllocationFamily Family) {
+ if (!State)
+ return nullptr;
+
// Get the return value.
SVal retVal = State->getSVal(E, C.getLocationContext());
@@ -992,11 +1074,14 @@
ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
const CallExpr *CE,
- const OwnershipAttr *Att) const {
+ const OwnershipAttr *Att,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (Att->getModule() != II_malloc)
return nullptr;
- ProgramStateRef State = C.getState();
bool ReleasedAllocated = false;
for (const auto &Arg : Att->args()) {
@@ -1011,15 +1096,18 @@
ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
const CallExpr *CE,
- ProgramStateRef state,
+ ProgramStateRef State,
unsigned Num,
bool Hold,
bool &ReleasedAllocated,
bool ReturnsNullOnFailure) const {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < (Num + 1))
return nullptr;
- return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
+ return FreeMemAux(C, CE->getArg(Num), CE, State, Hold,
ReleasedAllocated, ReturnsNullOnFailure);
}
@@ -1152,6 +1240,9 @@
bool &ReleasedAllocated,
bool ReturnsNullOnFailure) const {
+ if (!State)
+ return nullptr;
+
SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
if (!ArgVal.getAs<DefinedOrUnknownSVal>())
return nullptr;
@@ -1407,6 +1498,38 @@
}
}
+void MallocChecker::ReportZeroByteAllocation(CheckerContext &C,
+ ProgramStateRef FalseState,
+ const Expr *Arg,
+ const Expr *AllocExpr) const {
+ if (!ChecksEnabled[CK_MallocOptimistic] &&
+ !ChecksEnabled[CK_MallocPessimistic])
+ return;
+
+ auto CheckKind = getCheckIfTracked(C, AllocExpr);
+ if (!CheckKind.hasValue())
+ return;
+
+ if (ExplodedNode *N = C.generateSink(FalseState)) {
+
+ if (!BT_ZerroAllocation[*CheckKind])
+ BT_ZerroAllocation[*CheckKind].reset(new BugType(
+ CheckNames[*CheckKind], "Zero allocation", "Memory Error"));
+
+ SmallString<256> S;
+ llvm::raw_svector_ostream os(S);
+ os << "Call to '";
+ printAllocDeallocName(os, C, AllocExpr);
+ os << "' has an allocation size of 0 bytes";
+ BugReport *Report =
+ new BugReport(*BT_ZerroAllocation[*CheckKind], os.str(), N);
+
+ Report->addRange(Arg->getSourceRange());
+ bugreporter::trackNullOrUndefValue(N, Arg, *Report);
+ C.emitReport(Report);
+ }
+}
+
void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange Range,
const Expr *DeallocExpr) const {
@@ -1655,43 +1778,46 @@
ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
const CallExpr *CE,
- bool FreesOnFail) const {
+ bool FreesOnFail,
+ ProgramStateRef State) const {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < 2)
return nullptr;
- ProgramStateRef state = C.getState();
const Expr *arg0Expr = CE->getArg(0);
const LocationContext *LCtx = C.getLocationContext();
- SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
+ SVal Arg0Val = State->getSVal(arg0Expr, LCtx);
if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
SValBuilder &svalBuilder = C.getSValBuilder();
DefinedOrUnknownSVal PtrEQ =
- svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
+ svalBuilder.evalEQ(State, arg0Val, svalBuilder.makeNull());
// Get the size argument. If there is no size arg then give up.
const Expr *Arg1 = CE->getArg(1);
if (!Arg1)
return nullptr;
// Get the value of the size argument.
- SVal Arg1ValG = state->getSVal(Arg1, LCtx);
+ SVal Arg1ValG = State->getSVal(Arg1, LCtx);
if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
return nullptr;
DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
// Compare the size argument to 0.
DefinedOrUnknownSVal SizeZero =
- svalBuilder.evalEQ(state, Arg1Val,
+ svalBuilder.evalEQ(State, Arg1Val,
svalBuilder.makeIntValWithPtrWidth(0, false));
ProgramStateRef StatePtrIsNull, StatePtrNotNull;
- std::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
+ std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
ProgramStateRef StateSizeIsZero, StateSizeNotZero;
- std::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
+ std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
// We only assume exceptional states if they are definitely true; if the
// state is under-constrained, assume regular realloc behavior.
bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
@@ -1711,7 +1837,7 @@
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
assert(!PrtIsNull);
SymbolRef FromPtr = arg0Val.getAsSymbol();
- SVal RetVal = state->getSVal(CE, LCtx);
+ SVal RetVal = State->getSVal(CE, LCtx);
SymbolRef ToPtr = RetVal.getAsSymbol();
if (!FromPtr || !ToPtr)
return nullptr;
@@ -1731,7 +1857,7 @@
// Default behavior.
if (ProgramStateRef stateFree =
- FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) {
+ FreeMemAux(C, CE, State, 0, false, ReleasedAllocated)) {
ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
UnknownVal(), stateFree);
@@ -1755,20 +1881,23 @@
return nullptr;
}
-ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
+ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE,
+ ProgramStateRef State) {
+ if (!State)
+ return nullptr;
+
if (CE->getNumArgs() < 2)
return nullptr;
- ProgramStateRef state = C.getState();
SValBuilder &svalBuilder = C.getSValBuilder();
const LocationContext *LCtx = C.getLocationContext();
- SVal count = state->getSVal(CE->getArg(0), LCtx);
- SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
- SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
+ SVal count = State->getSVal(CE->getArg(0), LCtx);
+ SVal elementSize = State->getSVal(CE->getArg(1), LCtx);
+ SVal TotalSize = svalBuilder.evalBinOp(State, BO_Mul, count, elementSize,
svalBuilder.getContext().getSizeType());
SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
- return MallocMemAux(C, CE, TotalSize, zeroVal, state);
+ return MallocMemAux(C, CE, TotalSize, zeroVal, State);
}
LeakInfo
Index: lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -30,33 +30,18 @@
namespace {
class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
- mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
+ mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce;
mutable Optional<uint64_t> Val_O_CREAT;
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
- void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
- void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
- void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
- void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const;
- void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
- void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
const CallExpr *) const;
private:
- bool ReportZeroByteAllocation(CheckerContext &C,
- ProgramStateRef falseState,
- const Expr *arg,
- const char *fn_name) const;
- void BasicAllocationCheck(CheckerContext &C,
- const CallExpr *CE,
- const unsigned numArgs,
- const unsigned sizeArg,
- const char *fn) const;
void LazyInitialize(std::unique_ptr<BugType> &BT, const char *name) const {
if (BT)
return;
@@ -206,144 +191,6 @@
}
//===----------------------------------------------------------------------===//
-// "calloc", "malloc", "realloc", "reallocf", "alloca" and "valloc"
-// with allocation size 0
-//===----------------------------------------------------------------------===//
-// FIXME: Eventually these should be rolled into the MallocChecker, but right now
-// they're more basic and valuable for widespread use.
-
-// Returns true if we try to do a zero byte allocation, false otherwise.
-// Fills in trueState and falseState.
-static bool IsZeroByteAllocation(ProgramStateRef state,
- const SVal argVal,
- ProgramStateRef *trueState,
- ProgramStateRef *falseState) {
- std::tie(*trueState, *falseState) =
- state->assume(argVal.castAs<DefinedSVal>());
-
- return (*falseState && !*trueState);
-}
-
-// Generates an error report, indicating that the function whose name is given
-// will perform a zero byte allocation.
-// Returns false if an error occurred, true otherwise.
-bool UnixAPIChecker::ReportZeroByteAllocation(CheckerContext &C,
- ProgramStateRef falseState,
- const Expr *arg,
- const char *fn_name) const {
- ExplodedNode *N = C.generateSink(falseState);
- if (!N)
- return false;
-
- LazyInitialize(BT_mallocZero,
- "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
-
- SmallString<256> S;
- llvm::raw_svector_ostream os(S);
- os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
- BugReport *report = new BugReport(*BT_mallocZero, os.str(), N);
-
- report->addRange(arg->getSourceRange());
- bugreporter::trackNullOrUndefValue(N, arg, *report);
- C.emitReport(report);
-
- return true;
-}
-
-// Does a basic check for 0-sized allocations suitable for most of the below
-// functions (modulo "calloc")
-void UnixAPIChecker::BasicAllocationCheck(CheckerContext &C,
- const CallExpr *CE,
- const unsigned numArgs,
- const unsigned sizeArg,
- const char *fn) const {
- // Sanity check for the correct number of arguments
- if (CE->getNumArgs() != numArgs)
- return;
-
- // Check if the allocation size is 0.
- ProgramStateRef state = C.getState();
- ProgramStateRef trueState = nullptr, falseState = nullptr;
- const Expr *arg = CE->getArg(sizeArg);
- SVal argVal = state->getSVal(arg, C.getLocationContext());
-
- if (argVal.isUnknownOrUndef())
- return;
-
- // Is the value perfectly constrained to zero?
- if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
- (void) ReportZeroByteAllocation(C, falseState, arg, fn);
- return;
- }
- // Assume the value is non-zero going forward.
- assert(trueState);
- if (trueState != state)
- C.addTransition(trueState);
-}
-
-void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
- const CallExpr *CE) const {
- unsigned int nArgs = CE->getNumArgs();
- if (nArgs != 2)
- return;
-
- ProgramStateRef state = C.getState();
- ProgramStateRef trueState = nullptr, falseState = nullptr;
-
- unsigned int i;
- for (i = 0; i < nArgs; i++) {
- const Expr *arg = CE->getArg(i);
- SVal argVal = state->getSVal(arg, C.getLocationContext());
- if (argVal.isUnknownOrUndef()) {
- if (i == 0)
- continue;
- else
- return;
- }
-
- if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
- if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
- return;
- else if (i == 0)
- continue;
- else
- return;
- }
- }
-
- // Assume the value is non-zero going forward.
- assert(trueState);
- if (trueState != state)
- C.addTransition(trueState);
-}
-
-void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
- const CallExpr *CE) const {
- BasicAllocationCheck(C, CE, 1, 0, "malloc");
-}
-
-void UnixAPIChecker::CheckReallocZero(CheckerContext &C,
- const CallExpr *CE) const {
- BasicAllocationCheck(C, CE, 2, 1, "realloc");
-}
-
-void UnixAPIChecker::CheckReallocfZero(CheckerContext &C,
- const CallExpr *CE) const {
- BasicAllocationCheck(C, CE, 2, 1, "reallocf");
-}
-
-void UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
- const CallExpr *CE) const {
- BasicAllocationCheck(C, CE, 1, 0, "alloca");
-}
-
-void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
- const CallExpr *CE) const {
- BasicAllocationCheck(C, CE, 1, 0, "valloc");
-}
-
-
-//===----------------------------------------------------------------------===//
// Central dispatch function.
//===----------------------------------------------------------------------===//
@@ -361,12 +208,6 @@
llvm::StringSwitch<SubChecker>(FName)
.Case("open", &UnixAPIChecker::CheckOpen)
.Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
- .Case("calloc", &UnixAPIChecker::CheckCallocZero)
- .Case("malloc", &UnixAPIChecker::CheckMallocZero)
- .Case("realloc", &UnixAPIChecker::CheckReallocZero)
- .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
- .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
- .Case("valloc", &UnixAPIChecker::CheckVallocZero)
.Default(nullptr);
if (SC)
Index: test/Analysis/malloc-annotations.c
===================================================================
--- test/Analysis/malloc-annotations.c
+++ test/Analysis/malloc-annotations.c
@@ -43,7 +43,12 @@
void f2_realloc_1() {
int *p = malloc(12);
- int *q = realloc(p,0); // no-warning
+ int *q = realloc(p,0); // expected-warning{{Call to 'realloc()' has an allocation size of 0 bytes}}
+}
+
+void f2_realloc_2() {
+ int *p = malloc(12);
+ realloc(p,0); // no-warning
}
// ownership attributes tests
Index: test/Analysis/malloc.c
===================================================================
--- test/Analysis/malloc.c
+++ test/Analysis/malloc.c
@@ -5,6 +5,7 @@
void clang_analyzer_eval(int);
typedef __typeof(sizeof(int)) size_t;
+void *alloca(size_t);
void *malloc(size_t);
void *valloc(size_t);
void free(void *);
@@ -38,7 +39,7 @@
void f2_realloc_1() {
int *p = malloc(12);
- int *q = realloc(p,0); // no-warning
+ realloc(p,0); // no-warning
}
void reallocNotNullPtr(unsigned sizeIn) {
@@ -69,38 +70,17 @@
void reallocSizeZero1() {
char *p = malloc(12);
- char *r = realloc(p, 0);
- if (!r) {
- free(p); // expected-warning {{Attempt to free released memory}}
- } else {
- free(r);
- }
+ realloc(p, 0);
}
void reallocSizeZero2() {
char *p = malloc(12);
- char *r = realloc(p, 0);
- if (!r) {
- free(p); // expected-warning {{Attempt to free released memory}}
- } else {
- free(r);
- }
+ realloc(p, 0);
free(p); // expected-warning {{Attempt to free released memory}}
}
void reallocSizeZero3() {
- char *p = malloc(12);
- char *r = realloc(p, 0);
- free(r);
-}
-
-void reallocSizeZero4() {
- char *r = realloc(0, 0);
- free(r);
-}
-
-void reallocSizeZero5() {
- char *r = realloc(0, 0);
+ realloc(0, 0);
}
void reallocPtrZero1() {
@@ -949,6 +929,115 @@
}
// ----------------------------------------------------------------------------
+// Test zero-sized allocations.
+void testMallocZero() {
+ char* foo = malloc(0); // expected-warning{{Call to 'malloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testMallocZeroNoWarn(size_t size) {
+ char* foo = malloc(size); // no-warning
+ free(foo);
+}
+
+void testMallocPathZero(int i) {
+ if (!i) {
+ char* foo = malloc(i); // expected-warning{{Call to 'malloc()' has an allocation size of 0 bytes}}
+ free(foo);
+ }
+}
+
+// Perform inline defensive check.
+void idc(int i) {
+ if (i)
+ ;
+}
+void testMallocIdc(int i) {
+ idc(i);
+ char* foo = malloc(i); // no-warning
+ free(foo);
+}
+
+void testCallocZero(void) {
+ char *foo = calloc(0, 0); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testCalloc1Zero(void) {
+ char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testCalloc2Zero(void) {
+ char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testCalloc1Unknown2Zero(int *i, int j) {
+ char *foo = calloc(*(i+j), 0); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testCallocZeroNoWarn(size_t nmemb, size_t size) {
+ char *foo = calloc(nmemb, size); // no-warning
+ free(foo);
+}
+
+void testReallocZero(char *ptr) {
+ char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testReallocZeroNoWarn1(char *ptr) {
+ realloc(ptr, 0); // no-warning
+}
+
+void testReallocZeroNoWarn2(char *ptr, size_t size) {
+ char *foo = realloc(ptr, size); // no-warning
+ free(foo);
+}
+
+void testReallocfZero(char *ptr) {
+ char *foo = reallocf(ptr, 0); // expected-warning{{Call to 'reallocf()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testReallocfZeroNoWarn1(char *ptr) {
+ reallocf(ptr, 0); // no-warning
+}
+
+void testReallocfZeroNoWarn2(char *ptr, size_t size) {
+ char *foo = reallocf(ptr, size); // no-warning
+ free(foo);
+}
+
+void testAllocaZero() {
+ char *foo = alloca(0); // expected-warning{{Call to 'alloca()' has an allocation size of 0 bytes}}
+}
+
+void testAllocaZeroNoWarn(size_t sz) {
+ char *foo = alloca(sz); // no-warning
+}
+
+void testBuiltinAllocaZero() {
+ char *foo2 = __builtin_alloca(0); // expected-warning{{Call to '__builtin_alloca()' has an allocation size of 0 bytes}}
+}
+
+void testBuiltinAllocaZeroNoWarn(size_t sz) {
+ char *foo2 = __builtin_alloca(sz); // no-warning
+}
+
+void testVallocZero() {
+ char *foo = valloc(0); // expected-warning{{Call to 'valloc()' has an allocation size of 0 bytes}}
+ free(foo);
+}
+
+void testVallocZeroNoWarn(size_t sz) {
+ char *foo = valloc(sz); // no-warning
+ free(foo);
+}
+
+// ----------------------------------------------------------------------------
// Test the system library functions to which the pointer can escape.
// This tests false positive suppression.
Index: test/Analysis/unix-fns.c
===================================================================
--- test/Analysis/unix-fns.c
+++ test/Analysis/unix-fns.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,unix.API,osx.API %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,unix.API,osx.API,unix.Malloc %s -analyzer-store=region -analyzer-output=plist -analyzer-eagerly-assume -analyzer-config faux-bodies=true -analyzer-config path-diagnostics-alternate=false -fblocks -verify -o %t.plist
// RUN: FileCheck --input-file=%t.plist %s
// RUN: mkdir -p %t.dir
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API,osx.API -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API,osx.API,unix.Malloc -analyzer-output=html -analyzer-config faux-bodies=true -fblocks -o %t.dir %s
// RUN: rm -fR %t.dir
struct _opaque_pthread_once_t {
long __sig;
@@ -79,7 +79,7 @@
// PR 2899 - warn of zero-sized allocations to malloc().
void pr2899() {
- char* foo = malloc(0); // expected-warning{{Call to 'malloc' has an allocation size of 0 bytes}}
+ char* foo = malloc(0); // expected-warning{{Call to 'malloc()' has an allocation size of 0 bytes}}
for (unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
@@ -91,13 +91,13 @@
}
}
void test_calloc(void) {
- char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}}
+ char *foo = calloc(0, 42); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
for (unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
}
void test_calloc2(void) {
- char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc' has an allocation size of 0 bytes}}
+ char *foo = calloc(42, 0); // expected-warning{{Call to 'calloc()' has an allocation size of 0 bytes}}
for (unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
@@ -109,13 +109,13 @@
}
}
void test_realloc(char *ptr) {
- char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc' has an allocation size of 0 bytes}}
+ char *foo = realloc(ptr, 0); // expected-warning{{Call to 'realloc()' has an allocation size of 0 bytes}}
for (unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
}
void test_reallocf(char *ptr) {
- char *foo = reallocf(ptr, 0); // expected-warning{{Call to 'reallocf' has an allocation size of 0 bytes}}
+ char *foo = reallocf(ptr, 0); // expected-warning{{Call to 'reallocf()' has an allocation size of 0 bytes}}
for (unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
@@ -133,7 +133,7 @@
}
}
void test_alloca() {
- char *foo = alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}}
+ char *foo = alloca(0); // expected-warning{{Call to 'alloca()' has an allocation size of 0 bytes}}
for(unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
@@ -145,7 +145,7 @@
}
}
void test_builtin_alloca() {
- char *foo2 = __builtin_alloca(0); // expected-warning{{Call to 'alloca' has an allocation size of 0 bytes}}
+ char *foo2 = __builtin_alloca(0); // expected-warning{{Call to '__builtin_alloca()' has an allocation size of 0 bytes}}
for(unsigned i = 0; i < 100; i++) {
foo2[i] = 0;
}
@@ -157,7 +157,7 @@
}
}
void test_valloc() {
- char *foo = valloc(0); // expected-warning{{Call to 'valloc' has an allocation size of 0 bytes}}
+ char *foo = valloc(0); // expected-warning{{Call to 'valloc()' has an allocation size of 0 bytes}}
for(unsigned i = 0; i < 100; i++) {
foo[i] = 0;
}
@@ -706,14 +706,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'malloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'malloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'malloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'malloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'malloc' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'malloc()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>pr2899</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -786,14 +786,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'calloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'calloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'calloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'calloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'calloc' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'calloc()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_calloc</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -866,14 +866,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'calloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'calloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'calloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'calloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'calloc' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'calloc()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_calloc2</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -946,14 +946,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'realloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'realloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'realloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'realloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'realloc' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'realloc()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_realloc</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -1026,14 +1026,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'reallocf' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'reallocf()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'reallocf' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'reallocf()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'reallocf' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'reallocf()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_reallocf</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -1106,14 +1106,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'alloca' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'alloca()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'alloca' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'alloca()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'alloca' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'alloca()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_alloca</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -1186,14 +1186,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'alloca' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to '__builtin_alloca()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'alloca' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to '__builtin_alloca()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'alloca' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to '__builtin_alloca()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_builtin_alloca</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
@@ -1266,14 +1266,14 @@
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to 'valloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'valloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to 'valloc' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <string>Call to 'valloc()' has an allocation size of 0 bytes</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to 'valloc' has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>description</key><string>Call to 'valloc()' has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Memory Error</string>
+// CHECK-NEXT: <key>type</key><string>Zero allocation</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
// CHECK-NEXT: <key>issue_context</key><string>test_valloc</string>
// CHECK-NEXT: <key>issue_hash</key><string>1</string>
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits