summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2014-10-03 21:48:54 +0000
committerAnna Zaks <ganna@apple.com>2014-10-03 21:48:54 +0000
commit2d2f137ed4a794f494a6a763f342bba1ef492ed2 (patch)
tree66f2d536b796d347d2d52d0e3227f49d466ec788
parentde952d118003838ad4fd724bfabc5c3335ec9c27 (diff)
downloadbcm5719-llvm-2d2f137ed4a794f494a6a763f342bba1ef492ed2.tar.gz
bcm5719-llvm-2d2f137ed4a794f494a6a763f342bba1ef492ed2.zip
[analyzer] Make CStringChecker correctly calculate return value of mempcpy
The return value of mempcpy is only correct when the destination type is one byte in size. This patch casts the argument to a char* so the calculation is also correct for structs, ints etc. A patch by Daniel Fahlgren! llvm-svn: 219024
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp7
-rw-r--r--clang/test/Analysis/bstring.c39
2 files changed, 45 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 0693bd6fd94..e91a7e16802 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -969,8 +969,13 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
// Get the length to copy.
if (Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
// Get the byte after the last byte copied.
+ SValBuilder &SvalBuilder = C.getSValBuilder();
+ ASTContext &Ctx = SvalBuilder.getContext();
+ QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
+ loc::MemRegionVal DestRegCharVal = SvalBuilder.evalCast(destRegVal,
+ CharPtrTy, Dest->getType()).castAs<loc::MemRegionVal>();
SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
- destRegVal,
+ DestRegCharVal,
*lenValNonLoc,
Dest->getType());
diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c
index 69d281afee4..824aa7c063b 100644
--- a/clang/test/Analysis/bstring.c
+++ b/clang/test/Analysis/bstring.c
@@ -257,6 +257,45 @@ void mempcpy13() {
mempcpy(a, 0, 0); // no-warning
}
+void mempcpy14() {
+ int src[] = {1, 2, 3, 4};
+ int dst[5] = {0};
+ int *p;
+
+ p = mempcpy(dst, src, 4 * sizeof(int));
+
+ clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}}
+}
+
+struct st {
+ int i;
+ int j;
+};
+
+void mempcpy15() {
+ struct st s1 = {0};
+ struct st s2;
+ struct st *p1;
+ struct st *p2;
+
+ p1 = (&s2) + 1;
+ p2 = mempcpy(&s2, &s1, sizeof(struct st));
+
+ clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
+}
+
+void mempcpy16() {
+ struct st s1[10] = {{0}};
+ struct st s2[10];
+ struct st *p1;
+ struct st *p2;
+
+ p1 = (&s2[0]) + 5;
+ p2 = mempcpy(&s2[0], &s1[0], 5 * sizeof(struct st));
+
+ clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
+}
+
void mempcpy_unknown_size_warn (size_t n) {
char a[4];
void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}}
OpenPOWER on IntegriCloud