r334636 - [analyzer] Fix offset overflow check in MemRegion

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 13 11:32:19 PDT 2018


Author: george.karpenkov
Date: Wed Jun 13 11:32:19 2018
New Revision: 334636

URL: http://llvm.org/viewvc/llvm-project?rev=334636&view=rev
Log:
[analyzer] Fix offset overflow check in MemRegion

rdar://39593879
https://bugs.llvm.org/show_bug.cgi?id=37142

Differential Revision: https://reviews.llvm.org/D48139

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
    cfe/trunk/test/Analysis/region_store_overflow.c

Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=334636&r1=334635&r2=334636&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Wed Jun 13 11:32:19 2018
@@ -41,6 +41,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/CheckedArithmetic.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1181,38 +1182,8 @@ const SymbolicRegion *MemRegion::getSymb
   return nullptr;
 }
 
-/// Perform a given operation on two integers, return whether it overflows.
-/// Optionally write the resulting output into \p Res.
-static bool checkedOp(
-    int64_t LHS,
-    int64_t RHS,
-    std::function<llvm::APInt(llvm::APInt *, const llvm::APInt &, bool &)> Op,
-    int64_t *Res = nullptr) {
-  llvm::APInt ALHS(/*BitSize=*/64, LHS, /*Signed=*/true);
-  llvm::APInt ARHS(/*BitSize=*/64, RHS, /*Signed=*/true);
-  bool Overflow;
-  llvm::APInt Out = Op(&ALHS, ARHS, Overflow);
-  if (!Overflow && Res)
-    *Res = Out.getSExtValue();
-  return Overflow;
-}
-
-static bool checkedAdd(
-    int64_t LHS,
-    int64_t RHS,
-    int64_t *Res=nullptr) {
-  return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov, Res);
-}
-
-static bool checkedMul(
-    int64_t LHS,
-    int64_t RHS,
-    int64_t *Res=nullptr) {
-  return checkedOp(LHS, RHS, &llvm::APInt::smul_ov, Res);
-}
-
 RegionRawOffset ElementRegion::getAsArrayOffset() const {
-  CharUnits offset = CharUnits::Zero();
+  int64_t offset = 0;
   const ElementRegion *ER = this;
   const MemRegion *superR = nullptr;
   ASTContext &C = getContext();
@@ -1224,7 +1195,7 @@ RegionRawOffset ElementRegion::getAsArra
 
     // FIXME: generalize to symbolic offsets.
     SVal index = ER->getIndex();
-    if (Optional<nonloc::ConcreteInt> CI = index.getAs<nonloc::ConcreteInt>()) {
+    if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
       // Update the offset.
       int64_t i = CI->getValue().getSExtValue();
 
@@ -1237,20 +1208,15 @@ RegionRawOffset ElementRegion::getAsArra
           break;
         }
 
-        CharUnits size = C.getTypeSizeInChars(elemType);
-
-        int64_t Mult;
-        bool Overflow = checkedAdd(i, size.getQuantity(), &Mult);
-        if (!Overflow)
-          Overflow = checkedMul(Mult, offset.getQuantity());
-        if (Overflow) {
+        int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
+        if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
+          offset = *NewOffset;
+        } else {
           LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
                                   << "offset overflowing, returning unknown\n");
 
           return nullptr;
         }
-
-        offset += (i * size);
       }
 
       // Go to the next ElementRegion (if any).
@@ -1262,7 +1228,7 @@ RegionRawOffset ElementRegion::getAsArra
   }
 
   assert(superR && "super region cannot be NULL");
-  return RegionRawOffset(superR, offset);
+  return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
 }
 
 /// Returns true if \p Base is an immediate base class of \p Child

Modified: cfe/trunk/test/Analysis/region_store_overflow.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/region_store_overflow.c?rev=334636&r1=334635&r2=334636&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/region_store_overflow.c (original)
+++ cfe/trunk/test/Analysis/region_store_overflow.c Wed Jun 13 11:32:19 2018
@@ -1,6 +1,5 @@
 // RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -verify %s
 
-// expected-no-diagnostics
 int **h;
 int overflow_in_memregion(long j) {
   for (int l = 0;; ++l) {
@@ -9,3 +8,9 @@ int overflow_in_memregion(long j) {
   }
   return 0;
 }
+
+void rdar39593879(long long *d) {
+  long e, f;
+  e = f = d[1]; // no-crash
+  for (; d[e];) f-- > 0; // expected-warning{{relational comparison result unused}}; 
+}




More information about the cfe-commits mailing list