Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[analyzer] Simplify SVal for simple NonLoc->Loc casts #66498

Conversation

danix800
Copy link
Member

@danix800 danix800 commented Sep 15, 2023

NonLoc symbolic SVal to Loc casts are not supported except for nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
    long long t2 = t1 + 3;
    if (!t2) {
      int *p = (int *) t2;
      clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
    }
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p' is unknown.

Fixes #62232

NonLoc symbolic SVal to Loc casts are not supported except for
nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can
go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

  void test_simplified_before_cast_add(long long t1) {
    long long t2 = t1 + 3;
    if (!t2) {
      int *p = (int *) t2;
      clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
    }
  }

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p'
is unknown.

Fixes llvm#62232
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html labels Sep 15, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 15, 2023

@llvm/pr-subscribers-clang

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

Changes NonLoc symbolic SVal to Loc casts are not supported except for nonloc::ConcreteInt.

This change simplifies the source SVals so that the more casts can go through nonloc::ConcreteInt->loc::ConcreteInt path. For example:

void test_simplified_before_cast_add(long long t1) {
long long t2 = t1 + 3;
if (!t2) {
int *p = (int *) t2;
clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
}
}

If simplified, 't2' is 0, resulting 'p' is nullptr, otherwise 'p' is unknown.

Fixes #62232

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

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+2-1)
  • (modified) clang/test/Analysis/symbol-simplification-nonloc-loc.cpp (+27-1)
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 2a47116db55a1ad..7e431f7e598c4cb 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -264,7 +264,8 @@ ProgramStateRef ExprEngine::handleLValueBitCast(
   }
   // Delegate to SValBuilder to process.
   SVal OrigV = state->getSVal(Ex, LCtx);
-  SVal V = svalBuilder.evalCast(OrigV, T, ExTy);
+  SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
+  SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
   // Negate the result if we're treating the boolean as a signed i1
   if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
     V = svalBuilder.evalMinus(V.castAs<NonLoc>());
diff --git a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
index 485f68d9a5acfba..6cfe8da971429c3 100644
--- a/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
+++ b/clang/test/Analysis/symbol-simplification-nonloc-loc.cpp
@@ -1,6 +1,8 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection %s \
 // RUN:    -triple x86_64-pc-linux-gnu -verify
 
+void clang_analyzer_eval(int);
+
 #define BINOP(OP) [](auto x, auto y) { return x OP y; }
 
 template <typename BinOp>
@@ -73,3 +75,27 @@ void zoo1backwards() {
   *(0 + p) = nullptr;  // warn
   **(0 + p) = 'a';     // no-warning: this should be unreachable
 }
+
+void test_simplified_before_cast_add(long t1) {
+  long t2 = t1 + 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_sub(long t1) {
+  long t2 = t1 - 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}
+
+void test_simplified_before_cast_mul(long t1) {
+  long t2 = t1 * 3;
+  if (!t2) {
+    int *p = (int *) t2;
+    clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
+  }
+}

@steakhal
Copy link
Contributor

Pushed manually with an adjusted commit message:
7c9abbd

@steakhal steakhal closed this Sep 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang:static analyzer clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

core.NullDereference FN caused by ineffective simplification on loading SymExpr
3 participants