[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-06 Thread via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));

DonatNagyE wrote:

Thanks!

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal closed 
https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/70837

>From 2de19fc8e14319674ce87c18771ba1b8ba22f79b Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Mon, 23 Oct 2023 18:10:29 +0200
Subject: [PATCH 1/3] [analyzer] Fix assertion failure in
 CXXInstanceCall::getCXXThisVal

Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base->getType(), QualType())`,
but it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only
evaluates casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion
   ctor expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but
   SymbolRegion expects SymbolData symbols, not generic SymExprs, as stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an
   ElementRegion, you already have to have a SubRegion that you want to
   cast, but the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD
IMO this is still better than having a crash.

Fixes #69922
---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp |  5 ++---
 clang/test/Analysis/builtin_bitcast.cpp | 21 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..20bc64dc2631cec 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,9 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+  if (isa(ThisVal))
 return UnknownVal();
-
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..13475694d287a22 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}

>From bcb048c09dcc7bb2728d46afc0ff9a09cf71f663 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Tue, 31 Oct 2023 19:20:16 +0100
Subject: [PATCH 2/3] Add fixme and add the ineffective evalCast

---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp   | 9 +++--
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 5 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 20bc64dc2631cec..76fb7481f65194b 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -716,8 +716,13 @@ SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
   SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
-  if (isa(ThisVal))
-return UnknownVal();
+
+  if (isa(ThisVal)) {
+SValBuilder  = getState()->getStateManager().getSValBuilder();
+QualType OriginalTy = ThisVal.getType(SVB.getContext());
+return SVB.evalCast(ThisVal, Base->getType(), OriginalTy);
+  }
+
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index d89d82626f72694..9375f39b2d71dd4 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -980,6 +980,11 @@ class EvalCastVisitor : public 
SValVisitor {
   return 

[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));

steakhal wrote:

Fixed. Now using `size_t`.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));

steakhal wrote:

Yes, that is to form a `SymExpr`, which is a `SymbolVal` (NonLoc) wrapping a 
`BO_And` `SymIntExpr` I think.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-02 Thread via cfe-commits

https://github.com/DonatNagyE commented:

Basically LGTM, thanks for fixing this crash.

I don't give a formal approval because I didn't independently verify the 
correctness of the details, but I like the direction of the change.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-02 Thread via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));

DonatNagyE wrote:

What is the role of the `&` operator here? Is it just an arbitrary numerical 
operation that's not handled by the analyzer?

(No action needed, I'm just curious.) 

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-02 Thread via cfe-commits

https://github.com/DonatNagyE edited 
https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-02 Thread via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));

DonatNagyE wrote:

Do I see it correctly that `ptr_size` just an alias of `size_t`? If yes, then 
why don't you use the standard name?

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-10-31 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun approved this pull request.


https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

steakhal wrote:

> > WDYT?
> 
> I like this! I hope we do not add too much redundant work, but at least we 
> make it clear what is the plan to fix this in the future.

Please approve the PR again, so that I could merge this after I give some time 
for others to look at this.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-10-31 Thread Gábor Horváth via cfe-commits

Xazax-hun wrote:

> WDYT?

I like this! I hope we do not add too much redundant work, but at least we make 
it clear what is the plan to fix this in the future.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

https://github.com/steakhal edited 
https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

https://github.com/steakhal edited 
https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

steakhal wrote:

> Hmm, I wonder if we should leave a FIXME comment, but it looks good to me.

I was thinking where to put the FIXME, and as I explored that should be within 
the CastVisitor. After that, I argued, that then I should still have the 
(ineffective) `SVB.evalCast()` to actually exercise that path.
It should be a fancy way of returning `Unknown` now, but arguably for the 
better reason xD

@Xazax-hun WDYT?

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/70837

>From a7f64815f4986fad597b9cb2d1acce2de9ac20bf Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Mon, 23 Oct 2023 18:10:29 +0200
Subject: [PATCH 1/2] [analyzer] Fix assertion failure in
 CXXInstanceCall::getCXXThisVal

Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base->getType(), QualType())`,
but it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only
evaluates casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion
   ctor expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but
   SymbolRegion expects SymbolData symbols, not generic SymExprs, as stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an
   ElementRegion, you already have to have a SubRegion that you want to
   cast, but the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD
IMO this is still better than having a crash.

Fixes #69922
---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp |  5 ++---
 clang/test/Analysis/builtin_bitcast.cpp | 21 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..20bc64dc2631cec 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,9 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+  if (isa(ThisVal))
 return UnknownVal();
-
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..13475694d287a22 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}

>From 27d2b84e14d73dcc2385f202a204993f25235de4 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Tue, 31 Oct 2023 19:20:16 +0100
Subject: [PATCH 2/2] Add fixme and add the ineffective evalCast

---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp   | 9 +++--
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 5 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 20bc64dc2631cec..76fb7481f65194b 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -716,8 +716,13 @@ SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
   SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
-  if (isa(ThisVal))
-return UnknownVal();
+
+  if (isa(ThisVal)) {
+SValBuilder  = getState()->getStateManager().getSValBuilder();
+QualType OriginalTy = ThisVal.getType(SVB.getContext());
+return SVB.evalCast(ThisVal, Base->getType(), OriginalTy);
+  }
+
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index d89d82626f72694..9375f39b2d71dd4 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -980,6 +980,11 @@ class EvalCastVisitor : public 
SValVisitor {
   return 

[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Gábor Horváth via cfe-commits

Xazax-hun wrote:

Hmm, I wonder if we should leave a FIXME comment, but it looks good to me.

https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun approved this pull request.


https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread via cfe-commits

llvmbot wrote:




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

Author: Balazs Benics (steakhal)


Changes

Workaround the case when the `this` pointer is actually a `NonLoc`, by 
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to how 
casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base-getType(), QualType())`, 
but it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only evaluates 
casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion ctor 
expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but SymbolRegion 
expects SymbolData symbols, not generic SymExprs, as stated:

 // Because pointer arithmetic is represented by ElementRegion layers,
 // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an 
ElementRegion, you already have to have a SubRegion that you want to cast, but 
the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD IMO this is still 
better than having a crash.

Fixes #69922

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


2 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Core/CallEvent.cpp (+2-3) 
- (modified) clang/test/Analysis/builtin_bitcast.cpp (+21) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..20bc64dc2631cec 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,9 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+  if (isa(ThisVal))
 return UnknownVal();
-
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..13475694d287a22 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}

``




https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer] Fix assertion failure in CXXInstanceCall::getCXXThisVal (PR #70837)

2023-10-31 Thread Balazs Benics via cfe-commits

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

Workaround the case when the `this` pointer is actually a `NonLoc`, by 
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to how 
casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base->getType(), QualType())`, but 
it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only evaluates 
casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion ctor 
expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but SymbolRegion 
expects SymbolData symbols, not generic SymExprs, as stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an 
ElementRegion, you already have to have a SubRegion that you want to cast, but 
the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD IMO this is still 
better than having a crash.

Fixes #69922

>From a7f64815f4986fad597b9cb2d1acce2de9ac20bf Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Mon, 23 Oct 2023 18:10:29 +0200
Subject: [PATCH] [analyzer] Fix assertion failure in
 CXXInstanceCall::getCXXThisVal

Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base->getType(), QualType())`,
but it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only
evaluates casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion
   ctor expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but
   SymbolRegion expects SymbolData symbols, not generic SymExprs, as stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an
   ElementRegion, you already have to have a SubRegion that you want to
   cast, but the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD
IMO this is still better than having a crash.

Fixes #69922
---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp |  5 ++---
 clang/test/Analysis/builtin_bitcast.cpp | 21 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..20bc64dc2631cec 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,9 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+  if (isa(ThisVal))
 return UnknownVal();
-
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..13475694d287a22 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{ [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}

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