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

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

>From fce8354901c8831408ee2dd46373401df6185e9d Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbal...@gmail.com>
Date: Mon, 7 Oct 2024 17:00:04 +0200
Subject: [PATCH] [analyzer] Fix crash when casting the result of a malformed
 fptr call

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 actualy function that happens to
be called.

Nevertheless, let's not crash.

CPP-5768
---
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 12 ++++++------
 clang/test/Analysis/range_casts.c             |  9 +++++++++
 2 files changed, 15 insertions(+), 6 deletions(-)

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
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to