r305773 - [analyzer] Check NULL pointer dereference issue for memset function
Leslie Zhai via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 19 23:41:06 PDT 2017
Author: xiangzhai
Date: Tue Jun 20 01:41:06 2017
New Revision: 305773
URL: http://llvm.org/viewvc/llvm-project?rev=305773&view=rev
Log:
[analyzer] Check NULL pointer dereference issue for memset function
Reviewers: dcoughlin, zaks.anna, NoQ, danielmarjamaki
Reviewed By: NoQ, danielmarjamaki
Differential Revision: https://reviews.llvm.org/D31868
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
cfe/trunk/test/Analysis/null-deref-ps-region.c
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=305773&r1=305772&r2=305773&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Tue Jun 20 01:41:06 2017
@@ -120,6 +120,7 @@ public:
void evalStdCopy(CheckerContext &C, const CallExpr *CE) const;
void evalStdCopyBackward(CheckerContext &C, const CallExpr *CE) const;
void evalStdCopyCommon(CheckerContext &C, const CallExpr *CE) const;
+ void evalMemset(CheckerContext &C, const CallExpr *CE) const;
// Utility methods
std::pair<ProgramStateRef , ProgramStateRef >
@@ -1999,6 +2000,54 @@ void CStringChecker::evalStdCopyCommon(C
C.addTransition(State);
}
+void CStringChecker::evalMemset(CheckerContext &C, const CallExpr *CE) const {
+ if (CE->getNumArgs() != 3)
+ return;
+
+ CurrentFunctionDescription = "memory set function";
+
+ const Expr *Mem = CE->getArg(0);
+ const Expr *Size = CE->getArg(2);
+ ProgramStateRef State = C.getState();
+
+ // See if the size argument is zero.
+ const LocationContext *LCtx = C.getLocationContext();
+ SVal SizeVal = State->getSVal(Size, LCtx);
+ QualType SizeTy = Size->getType();
+
+ ProgramStateRef StateZeroSize, StateNonZeroSize;
+ std::tie(StateZeroSize, StateNonZeroSize) =
+ assumeZero(C, State, SizeVal, SizeTy);
+
+ // Get the value of the memory area.
+ SVal MemVal = State->getSVal(Mem, LCtx);
+
+ // If the size is zero, there won't be any actual memory access, so
+ // just bind the return value to the Mem buffer and return.
+ if (StateZeroSize && !StateNonZeroSize) {
+ StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal);
+ C.addTransition(StateZeroSize);
+ return;
+ }
+
+ // Ensure the memory area is not null.
+ // If it is NULL there will be a NULL pointer dereference.
+ State = checkNonNull(C, StateNonZeroSize, Mem, MemVal);
+ if (!State)
+ return;
+
+ State = CheckBufferAccess(C, State, Size, Mem);
+ if (!State)
+ return;
+ State = InvalidateBuffer(C, State, Mem, C.getSVal(Mem),
+ /*IsSourceBuffer*/false, Size);
+ if (!State)
+ return;
+
+ State = State->BindExpr(CE, LCtx, MemVal);
+ C.addTransition(State);
+}
+
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name) {
IdentifierInfo *II = FD->getIdentifier();
if (!II)
@@ -2032,6 +2081,8 @@ bool CStringChecker::evalCall(const Call
evalFunction = &CStringChecker::evalMemcmp;
else if (C.isCLibraryFunction(FDecl, "memmove"))
evalFunction = &CStringChecker::evalMemmove;
+ else if (C.isCLibraryFunction(FDecl, "memset"))
+ evalFunction = &CStringChecker::evalMemset;
else if (C.isCLibraryFunction(FDecl, "strcpy"))
evalFunction = &CStringChecker::evalStrcpy;
else if (C.isCLibraryFunction(FDecl, "strncpy"))
Modified: cfe/trunk/test/Analysis/null-deref-ps-region.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/null-deref-ps-region.c?rev=305773&r1=305772&r2=305773&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/null-deref-ps-region.c (original)
+++ cfe/trunk/test/Analysis/null-deref-ps-region.c Tue Jun 20 01:41:06 2017
@@ -1,6 +1,11 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -std=gnu99 -analyzer-store=region -verify %s
-// expected-no-diagnostics
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,unix,alpha.unix -std=gnu99 -analyzer-store=region -verify %s
+#include "Inputs/system-header-simulator.h"
+
+typedef __typeof(sizeof(int)) size_t;
+void *memset(void *__s, int __c, size_t __n);
+void *malloc(size_t __size);
+void free(void *__ptr);
// The store for 'a[1]' should not be removed mistakenly. SymbolicRegions may
// also be live roots.
@@ -13,3 +18,55 @@ void f14(int *a) {
i = *p; // no-warning
}
}
+
+void foo() {
+ int *x = malloc(sizeof(int));
+ memset(x, 0, sizeof(int));
+ int n = 1 / *x; // FIXME: no-warning
+ free(x);
+}
+
+void bar() {
+ int *x = malloc(sizeof(int));
+ memset(x, 0, 1);
+ int n = 1 / *x; // no-warning
+ free(x);
+}
+
+void testConcreteNull() {
+ int *x = 0;
+ memset(x, 0, 1); // expected-warning {{Null pointer argument in call to memory set function}}
+}
+
+void testStackArray() {
+ char buf[13];
+ memset(buf, 0, 1); // no-warning
+}
+
+void testHeapSymbol() {
+ char *buf = (char *)malloc(13);
+ memset(buf, 0, 1); // no-warning
+ free(buf);
+}
+
+void testStackArrayOutOfBound() {
+ char buf[1];
+ memset(buf, 0, 1024); // expected-warning {{Memory set function accesses out-of-bound array element}}
+}
+
+void testHeapSymbolOutOfBound() {
+ char *buf = (char *)malloc(1);
+ memset(buf, 0, 1024); // expected-warning {{Memory set function accesses out-of-bound array element}}
+ free(buf);
+}
+
+void testStackArraySameSize() {
+ char buf[1];
+ memset(buf, 0, sizeof(buf)); // no-warning
+}
+
+void testHeapSymbolSameSize() {
+ char *buf = (char *)malloc(1);
+ memset(buf, 0, 1); // no-warning
+ free(buf);
+}
More information about the cfe-commits
mailing list