devnexen updated this revision to Diff 176722.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D54592/new/
https://reviews.llvm.org/D54592
Files:
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
test/Analysis/string.c
Index: test/Analysis/string.c
===================================================================
--- test/Analysis/string.c
+++ test/Analysis/string.c
@@ -1184,11 +1184,14 @@
}
//===----------------------------------------------------------------------===
-// memset()
+// memset() / explicit_bzero() / bzero()
//===----------------------------------------------------------------------===
void *memset(void *dest, int ch, size_t count);
+void bzero(void *dst, size_t count);
+void explicit_bzero(void *dest, size_t count);
+
void *malloc(size_t size);
void free(void *);
@@ -1383,6 +1386,45 @@
clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}}
}
+void bzero1_null() {
+ char *a = NULL;
+
+ bzero(a, 10); // expected-warning{{Null pointer argument in call to memory clearance function}}
+}
+
+void bzero2_char_array_null() {
+ char str[] = "abcd";
+ clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}}
+ bzero(str, 2);
+ clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}}
+}
+
+void explicit_bzero1_null() {
+ char *a = NULL;
+
+ explicit_bzero(a, 10); // expected-warning{{Null pointer argument in call to memory clearance function}}
+}
+
+void explicit_bzero2_clear_mypassword() {
+ char passwd[7] = "passwd";
+
+ explicit_bzero(passwd, sizeof(passwd)); // no-warning
+
+ clang_analyzer_eval(strlen(passwd) == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(passwd[0] == '\0'); // expected-warning{{UNKNOWN}}
+}
+
+#ifdef SUPPRESS_OUT_OF_BOUND
+void explicit_bzero3_out_ofbound() {
+ char *privkey = (char *)malloc(6);
+ const char newprivkey[10] = "mysafekey";
+
+ strcpy(privkey, "random");
+ explicit_bzero(privkey, sizeof(newprivkey));
+ clang_analyzer_eval(privkey[0] == '\0'); // expected-warning{{UNKNOWN}}
+ free(privkey);
+}
+#endif
//===----------------------------------------------------------------------===
// FIXMEs
//===----------------------------------------------------------------------===
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -124,6 +124,7 @@
void evalStdCopyBackward(CheckerContext &C, const CallExpr *CE) const;
void evalStdCopyCommon(CheckerContext &C, const CallExpr *CE) const;
void evalMemset(CheckerContext &C, const CallExpr *CE) const;
+ void evalExplicitBzero(CheckerContext &C, const CallExpr *CE) const;
// Utility methods
std::pair<ProgramStateRef , ProgramStateRef >
@@ -158,7 +159,7 @@
static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR);
- static bool memsetAux(const Expr *DstBuffer, const Expr *CharE,
+ static bool memsetAux(const Expr *DstBuffer, SVal CharE,
const Expr *Size, CheckerContext &C,
ProgramStateRef &State);
@@ -1005,11 +1006,10 @@
}
}
-bool CStringChecker::memsetAux(const Expr *DstBuffer, const Expr *CharE,
+bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal,
const Expr *Size, CheckerContext &C,
ProgramStateRef &State) {
SVal MemVal = C.getSVal(DstBuffer);
- SVal CharVal = C.getSVal(CharE);
SVal SizeVal = C.getSVal(Size);
const MemRegion *MR = MemVal.getAsRegion();
if (!MR)
@@ -2184,13 +2184,54 @@
// According to the values of the arguments, bind the value of the second
// argument to the destination buffer and set string length, or just
// invalidate the destination buffer.
- if (!memsetAux(Mem, CharE, Size, C, State))
+ if (!memsetAux(Mem, C.getSVal(CharE), Size, C, State))
return;
State = State->BindExpr(CE, LCtx, MemVal);
C.addTransition(State);
}
+void CStringChecker::evalExplicitBzero(CheckerContext &C, const CallExpr *CE) const {
+ if (CE->getNumArgs() != 2)
+ return;
+
+ CurrentFunctionDescription = "memory clearance function";
+
+ const Expr *Mem = CE->getArg(0);
+ const Expr *Size = CE->getArg(1);
+ SVal Zero = C.getSValBuilder().makeZeroVal(Size->getType());
+
+ ProgramStateRef State = C.getState();
+
+ // See if the size argument is zero.
+ SVal SizeVal = C.getSVal(Size);
+ QualType SizeTy = Size->getType();
+
+ ProgramStateRef StateZeroSize, StateNonZeroSize;
+ std::tie(StateZeroSize, StateNonZeroSize) =
+ assumeZero(C, State, SizeVal, SizeTy);
+
+ // If the size is zero, there won't be any actual memory access,
+ // In this case we just return.
+ if (StateZeroSize && !StateNonZeroSize)
+ return;
+
+ // Get the value of the memory area.
+ SVal MemVal = C.getSVal(Mem);
+
+ // 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;
+
+ memsetAux(Mem, Zero, Size, C, State);
+}
+
static bool isCPPStdLibraryFunction(const FunctionDecl *FD, StringRef Name) {
IdentifierInfo *II = FD->getIdentifier();
if (!II)
@@ -2224,7 +2265,8 @@
evalFunction = &CStringChecker::evalMemcmp;
else if (C.isCLibraryFunction(FDecl, "memmove"))
evalFunction = &CStringChecker::evalMemmove;
- else if (C.isCLibraryFunction(FDecl, "memset"))
+ else if (C.isCLibraryFunction(FDecl, "memset") ||
+ C.isCLibraryFunction(FDecl, "explicit_memset"))
evalFunction = &CStringChecker::evalMemset;
else if (C.isCLibraryFunction(FDecl, "strcpy"))
evalFunction = &CStringChecker::evalStrcpy;
@@ -2262,6 +2304,9 @@
evalFunction = &CStringChecker::evalStdCopy;
else if (isCPPStdLibraryFunction(FDecl, "copy_backward"))
evalFunction = &CStringChecker::evalStdCopyBackward;
+ else if (C.isCLibraryFunction(FDecl, "bzero") ||
+ C.isCLibraryFunction(FDecl, "explicit_bzero"))
+ evalFunction = &CStringChecker::evalExplicitBzero;
// If the callee isn't a string function, let another checker handle it.
if (!evalFunction)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits