vabridgers updated this revision to Diff 403276.
vabridgers added a comment.

- update test case
- add initial Loc bitwidth check for evalBinOpLL for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D118050/new/

https://reviews.llvm.org/D118050

Files:
  clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  clang/test/Analysis/cstring-checker-addressspace.c

Index: clang/test/Analysis/cstring-checker-addressspace.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/cstring-checker-addressspace.c
@@ -0,0 +1,27 @@
+// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \
+// RUN: -analyze -analyzer-checker=core,alpha.unix.cstring \
+// RUN: -analyze -analyzer-checker=debug.ExprInspection \
+// RUN: -analyzer-config crosscheck-with-z3=true -verify %s \
+// RUN: -Wno-incompatible-library-redeclaration
+// REQUIRES: z3
+
+void clang_analyzer_warnIfReached();
+
+// From https://llvm.org/docs/AMDGPUUsage.html#address-spaces,
+// select address space 3 (local), since the pointer size is
+// different than Generic.
+#define DEVICE __attribute__((address_space(3)))
+_Static_assert(sizeof(int *) == 8, "");
+_Static_assert(sizeof(DEVICE int *) == 4, "");
+
+DEVICE void *memcpy(DEVICE void *, const void *, unsigned long);
+
+// Copy from host to device memory.
+DEVICE void *memcpy(DEVICE void *dst, const void *src, unsigned long len);
+
+void top(DEVICE int *dst, int *src, int len) {
+  memcpy(dst, src, len);
+
+  // Create a bugreport for triggering Z3 refutation.
+  clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+}
Index: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -715,11 +715,57 @@
   llvm_unreachable("Fields not found in parent record's definition");
 }
 
+static uint64_t getLocBitwidth(ProgramStateRef State, Loc loc) {
+  uint64_t LocBitwidth = 0;
+  ASTContext &Ctx = State->getStateManager().getContext();
+
+  switch (loc.getSubKind()) {
+  default:
+    llvm_unreachable("Unhandled loc subkind in getLocBitwidth");
+    break;
+  case loc::MemRegionValKind: {
+    const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
+    if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
+      QualType Ty = SR->getSymbol()->getType();
+      if (!Ty.isNull())
+        LocBitwidth = Ctx.getTypeSize(Ty);
+    }
+  } break;
+  case loc::ConcreteIntKind: {
+    SVal V = State->getSVal(loc);
+    QualType Ty = V.getType(Ctx);
+    if (!Ty.isNull())
+      LocBitwidth = Ctx.getTypeSize(Ty);
+  } break;
+  case loc::GotoLabelKind:
+    break;
+  }
+  return LocBitwidth;
+}
+
+static bool compareLocBitWidth(ProgramStateRef State, Loc RhsLoc, Loc LhsLoc) {
+  uint64_t RhsBitwidth = getLocBitwidth(State, RhsLoc);
+  uint64_t LhsBitwidth = getLocBitwidth(State, LhsLoc);
+  if (RhsBitwidth && LhsBitwidth) {
+    assert(RhsBitwidth == LhsBitwidth &&
+           "RhsLoc bitwidth must be same as LhsLoc bitwidth!");
+    return RhsBitwidth == LhsBitwidth;
+  }
+  return false;
+}
+
 // FIXME: all this logic will change if/when we have MemRegion::getLocation().
 SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
                                   BinaryOperator::Opcode op,
                                   Loc lhs, Loc rhs,
                                   QualType resultTy) {
+
+  // Assert that bitwidth of lhs and rhs are the same.
+  // This can happen if two different address spaces are used,
+  // and the bitwidths of the address spaces are different.
+  // See LIT case clang/test/Analysis/cstring-checker-addressspace.c
+  compareLocBitWidth(state, rhs, lhs);
+
   // Only comparisons and subtractions are valid operations on two pointers.
   // See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15].
   // However, if a pointer is casted to an integer, evalBinOpNN may end up
Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -449,6 +449,11 @@
 
   ProgramStateRef stateTrue, stateFalse;
 
+  // Assume different address spaces cannot overlap.
+  if (First.Expression->getType()->getPointeeType().getAddressSpace() !=
+      Second.Expression->getType()->getPointeeType().getAddressSpace())
+    return state;
+
   // Get the buffer values and make sure they're known locations.
   const LocationContext *LCtx = C.getLocationContext();
   SVal firstVal = state->getSVal(First.Expression, LCtx);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to