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

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 08:07:40 PDT 2024


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



More information about the cfe-commits mailing list