NoQ updated this revision to Diff 179228.
NoQ added a comment.

Add a few more tests, just in case.


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

https://reviews.llvm.org/D55875

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
  lib/StaticAnalyzer/Core/SVals.cpp
  lib/StaticAnalyzer/Core/Store.cpp
  test/Analysis/casts.c

Index: test/Analysis/casts.c
===================================================================
--- test/Analysis/casts.c
+++ test/Analysis/casts.c
@@ -213,3 +213,35 @@
 }
 
 #endif
+
+char no_crash_SymbolCast_of_float_type_aux(int *p) {
+  *p += 1;
+  return *p;
+}
+
+void no_crash_SymbolCast_of_float_type() {
+  extern float x;
+  char (*f)() = no_crash_SymbolCast_of_float_type_aux;
+  f(&x);
+}
+
+double no_crash_reinterpret_double_as_int(double a) {
+  *(int *)&a = 1;
+  return a * a;
+}
+
+double no_crash_reinterpret_double_as_ptr(double a) {
+  *(void **)&a = 0;
+  return a * a;
+}
+
+double no_crash_reinterpret_double_as_sym_int(double a, int b) {
+  *(int *)&a = b;
+  return a * a;
+}
+
+double no_crash_reinterpret_double_as_sym_ptr(double a, void * b) {
+  *(void **)&a = b;
+  return a * a;
+}
+
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -394,14 +394,29 @@
   return UnknownVal();
 }
 
+static bool isScalarEnoughToAttemptACast(QualType T) {
+  return T->isIntegralOrEnumerationType() || Loc::isLocType(T);
+}
+
 /// CastRetrievedVal - Used by subclasses of StoreManager to implement
 ///  implicit casts that arise from loads from regions that are reinterpreted
 ///  as another region.
 SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
-                                    QualType castTy) {
-  if (castTy.isNull() || V.isUnknownOrUndef())
+                                    QualType CastTy) {
+  if (CastTy.isNull() || V.isUnknownOrUndef())
+    return V;
+
+  QualType OrigTy = V.detectType(StateMgr.getContext());
+  if (OrigTy.isNull())
     return V;
 
+  if (!isScalarEnoughToAttemptACast(OrigTy) ||
+      !isScalarEnoughToAttemptACast(CastTy)) {
+    if (OrigTy.getUnqualifiedType() == CastTy.getUnqualifiedType())
+      return V;
+    return UnknownVal();
+  }
+
   // When retrieving symbolic pointer and expecting a non-void pointer,
   // wrap them into element regions of the expected type if necessary.
   // SValBuilder::dispatchCast() doesn't do that, but it is necessary to
@@ -410,13 +425,13 @@
   // We might need to do that for non-void pointers as well.
   // FIXME: We really need a single good function to perform casts for us
   // correctly every time we need it.
-  if (castTy->isPointerType() && !castTy->isVoidPointerType())
+  if (CastTy->isPointerType() && !CastTy->isVoidPointerType())
     if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
       if (SR->getSymbol()->getType().getCanonicalType() !=
-          castTy.getCanonicalType())
-        return loc::MemRegionVal(castRegion(SR, castTy));
+          CastTy.getCanonicalType())
+        return loc::MemRegionVal(castRegion(SR, CastTy));
 
-  return svalBuilder.dispatchCast(V, castTy);
+  return svalBuilder.dispatchCast(V, CastTy);
 }
 
 SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
Index: lib/StaticAnalyzer/Core/SVals.cpp
===================================================================
--- lib/StaticAnalyzer/Core/SVals.cpp
+++ lib/StaticAnalyzer/Core/SVals.cpp
@@ -21,6 +21,7 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
 #include "llvm/ADT/Optional.h"
@@ -185,6 +186,59 @@
   return DD;
 }
 
+namespace {
+class TypeDetector : public SValVisitor<TypeDetector, QualType> {
+  ASTContext &ACtx;
+
+public:
+  TypeDetector(ASTContext &ACtx): ACtx(ACtx) {}
+
+  QualType VisitSVal(SVal V) { return QualType(); }
+
+  QualType VisitNonLocSymbolVal(nonloc::SymbolVal V) {
+    return V.getSymbol()->getType();
+  }
+
+  QualType VisitLocMemRegionVal(loc::MemRegionVal V) {
+    if (const auto *TR = dyn_cast<TypedRegion>(V.getRegion()))
+      return TR->getLocationType();
+    else
+      return ACtx.VoidPtrTy;
+  }
+
+  QualType VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
+    const llvm::APSInt &I = V.getValue();
+    return ACtx.getIntTypeForBitwidth(I.getBitWidth(), I.isSigned());
+  }
+
+  QualType VisitLocConcreteInt(loc::ConcreteInt V) {
+    return ACtx.VoidPtrTy;
+  }
+
+  QualType VisitNonLocLocAsInteger(nonloc::LocAsInteger V) {
+    // FIXME: This returns an unsigned type because LocAsInteger
+    // does not remember what is the correct type.
+    return ACtx.getIntTypeForBitwidth(V.getNumBits(), false);
+  }
+
+  QualType VisitNonLocCompoundVal(nonloc::CompoundVal V) {
+    return V.getValue()->getType();
+  }
+
+  QualType VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V) {
+    if (const auto *TVR = dyn_cast<TypedValueRegion>(V.getRegion()))
+      return TVR->getValueType();
+    return QualType();
+  }
+
+  // TODO: VisitNonLocPointerToMember!
+};
+}
+
+QualType SVal::detectType(ASTContext &ACtx) const {
+  return TypeDetector(ACtx).Visit(*this);
+}
+
 //===----------------------------------------------------------------------===//
 // Other Iterators.
 //===----------------------------------------------------------------------===//
Index: include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -205,6 +205,8 @@
   SymExpr::symbol_iterator symbol_end() const {
     return SymExpr::symbol_end();
   }
+
+  QualType detectType(ASTContext &ACtx) const;
 };
 
 inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {
Index: include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -53,6 +53,8 @@
   iterator begin() const { return L.begin(); }
   iterator end() const { return L.end(); }
 
+  QualType getType() const { return T; }
+
   static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
                       llvm::ImmutableList<SVal> L);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to