[clang] [analyzer] Fix crash when casting the result of a malformed fptr call (PR #111390)

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 08:08:03 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Balazs Benics (steakhal)

<details>
<summary>Changes</summary>

Ideally, we wouldn't workaround our current cast-modeling, but the experimental "support-symbolic-integer-casts" is not finished so we need to live with our current modeling.

Ideally, we could probably bind `UndefinedVal` as the result of the call even without evaluating the call, as the result types mismatch between the static type of the `CallExpr` and the actually function that happens to be called.

Nevertheless, let's not crash.
https://compiler-explorer.com/z/WvcqK6MbY

CPP-5768

---
Full diff: https://github.com/llvm/llvm-project/pull/111390.diff


2 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Core/SValBuilder.cpp (+6-6) 
- (modified) clang/test/Analysis/range_casts.c (+9) 


``````````diff
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index cb5fcbade2cfc2..92e9d245520345 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -600,8 +600,9 @@ SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
   if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
     return evalCast(val, castTy, originalTy);
 
-  SymbolRef se = val.getAsSymbol();
-  if (!se) // Let evalCast handle non symbolic expressions.
+  auto AsNonLoc = val.getAs<NonLoc>();
+  SymbolRef AsSymbol = val.getAsSymbol();
+  if (!AsSymbol || !AsNonLoc) // Let evalCast handle non symbolic expressions.
     return evalCast(val, castTy, originalTy);
 
   // Find the maximum value of the target type.
@@ -613,15 +614,14 @@ SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
 
   // Check the range of the symbol being casted against the maximum value of the
   // target type.
-  NonLoc FromVal = val.castAs<NonLoc>();
   QualType CmpTy = getConditionType();
-  NonLoc CompVal =
-      evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
+  NonLoc CompVal = evalBinOpNN(state, BO_LE, *AsNonLoc, ToTypeMaxVal, CmpTy)
+                       .castAs<NonLoc>();
   ProgramStateRef IsNotTruncated, IsTruncated;
   std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
   if (!IsNotTruncated && IsTruncated) {
     // Symbol is truncated so we evaluate it as a cast.
-    return makeNonLoc(se, originalTy, castTy);
+    return makeNonLoc(AsSymbol, originalTy, castTy);
   }
   return evalCast(val, castTy, originalTy);
 }
diff --git a/clang/test/Analysis/range_casts.c b/clang/test/Analysis/range_casts.c
index b1967730bf8613..8a3b610fd63dc1 100644
--- a/clang/test/Analysis/range_casts.c
+++ b/clang/test/Analysis/range_casts.c
@@ -154,3 +154,12 @@ void f15(long foo)
   else
     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 }
+
+int *getIntPtr(void) {
+  extern int *intPtr;
+  return intPtr;
+}
+char call_malformed_fptr() {
+  int (*fptr)(void) = (int (*)(void))getIntPtr;
+  return fptr(); // no-crash
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/111390


More information about the cfe-commits mailing list