[clang] [clang][analyzer] Improve documentation of checker 'cplusplus.Move' (NFC) (PR #96295)

2024-06-21 Thread Donát Nagy via cfe-commits

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


[clang] [clang][analyzer] Improve documentation of checker 'cplusplus.Move' (NFC) (PR #96295)

2024-06-21 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

LGTM, thanks for updating the docs!

I only have one minor inline remark about formatting.

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


[clang] [clang][analyzer] Improve documentation of checker 'cplusplus.Move' (NFC) (PR #96295)

2024-06-21 Thread Donát Nagy via cfe-commits


@@ -420,21 +420,52 @@ around, such as ``std::string_view``.
 
 cplusplus.Move (C++)
 
-Method calls on a moved-from object and copying a moved-from object will be 
reported.
-
+Find use-after-move bugs in C++. This includes method calls on moved-from
+objects, assignment of a moved-from object, and repeated move of a moved-from
+object.
 
 .. code-block:: cpp
 
-  struct A {
+ struct A {
void foo() {}
  };
 
- void f() {
+ void f1() {
A a;
A b = std::move(a); // note: 'a' became 'moved-from' here
a.foo();// warn: method call on a 'moved-from' object 'a'
  }
 
+ void f2() {
+   A a;
+   A b = std::move(a);
+   A c(std::move(a)); // warn: move of an already moved-from object
+ }
+
+ void f3() {
+   A a;
+   A b = std::move(a);
+   b = a; // warn: copy of moved-from object
+ }
+
+The checker option ``WarnOn`` controls on what objects the use-after-move is
+checked. The most strict value is ``KnownsOnly``, in this mode only objects are
+checked whose type is known to be move-unsafe. These include most STL objects
+(but excluding move-safe ones) and smart pointers. With option value
+``KnownsAndLocals`` local variables (of any type) are additionally checked. The
+idea behind this is that local variables are usually not tempting to be re-used
+so an use after move is more likely a bug than with member variables. With
+option value ``All`` any use-after move condition is checked on all kinds of
+variables, excluding global variables and known move-safe cases. Default value
+is ``KnownsAndLocals``.

NagyDonat wrote:

```suggestion
The checker option ``WarnOn`` controls on what objects the use-after-move is
checked.
* The most strict value is ``KnownsOnly``, in this mode only objects are
  checked whose type is known to be move-unsafe. These include most STL objects
  (but excluding move-safe ones) and smart pointers.
* With option value ``KnownsAndLocals`` local variables (of any type) are
  additionally checked. The idea behind this is that local variables are
  usually not tempting to be re-used so an use after move is more likely a bug
  than with member variables.
* With option value ``All`` any use-after move condition is checked on all
  kinds of variables, excluding global variables and known move-safe cases.
Default value is ``KnownsAndLocals``.
```
This paragraph was very long, re-flow it into a bullet point list.

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


[clang] [clang][analyzer] Improve documentation of checker 'cplusplus.Move' (NFC) (PR #96295)

2024-06-21 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-21 Thread Donát Nagy via cfe-commits


@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"
 " numerator is not a multiple of denominator")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
-" numerator is not a multiple of denominator")
+  diag(E->getOperatorLoc(),
+   "suspicious usage of 'sizeof(array)/sizeof(...)':"

NagyDonat wrote:

It would be slightly better in isolation, but all the other diagnostics look 
like e.g. `suspicious usage of 'sizeof(..., ...)'` or `suspicious usage of 
'sizeof(this)'; did you mean 'sizeof(*this)'` so for the sake of consistency 
I'd like to leave this aspect of the messages unchanged.

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-20 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/95550

From 06adc063c2388ea534537f5a417751fdf64b22cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Fri, 14 Jun 2024 15:16:34 +0200
Subject: [PATCH 1/3] [clang-tidy] Clarify diagnostics of
 bugprone-sizeof-expression

...becasue they were strangely worded and in a few cases outright
incorrect.
---
 .../bugprone/SizeofExpressionCheck.cpp| 22 ++---
 .../checkers/bugprone/sizeof-expression-2.c   | 12 +--
 .../sizeof-expression-any-pointer.cpp | 86 +--
 ...on-warn-on-sizeof-pointer-to-aggregate.cpp |  4 +-
 .../checkers/bugprone/sizeof-expression.cpp   | 84 +-
 5 files changed, 105 insertions(+), 103 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index c25ee42d0899a..3afa0e5c39882 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -296,7 +296,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   } else if (const auto *E =
  Result.Nodes.getNodeAs("sizeof-integer-call")) {
 diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
-   "that results in an integer")
+   "of integer type")
 << E->getSourceRange();
   } else if (const auto *E = Result.Nodes.getNodeAs("sizeof-this")) {
 diag(E->getBeginLoc(),
@@ -314,7 +314,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   << E->getSourceRange();
 } else {
   diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
- "that results in a pointer")
+ "of pointer type")
   << E->getSourceRange();
 }
   } else if (const auto *E = Result.Nodes.getNodeAs(
@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"
 " numerator is not a multiple of denominator")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
-" numerator is not a multiple of denominator")
+  diag(E->getOperatorLoc(),
+   "suspicious usage of 'sizeof(array)/sizeof(...)':"
+   " denominator differs from the size of array elements")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (NumTy && DenomTy && NumTy == DenomTy) {
-  // FIXME: This message is wrong, it should not refer to sizeof "pointer"
-  // usage (and by the way, it would be to clarify all the messages).
   diag(E->getOperatorLoc(),
-   "suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'")
+   "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+   "have the same type")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (!WarnOnSizeOfPointer) {
   // When 'WarnOnSizeOfPointer' is enabled, these messages become 
redundant:
   if (PointedTy && DenomTy && PointedTy == DenomTy) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': size of pointer "
+ "is divided by size of pointed type")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   } else if (NumTy && DenomTy && NumTy->isPointerType() &&
  DenomTy->isPointerType()) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+ "have pointer types")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   }
 }
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
index aef930f2c8fda..b898071a56613 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
@@ -34,24 +34,24 @@ int Test5() {
 
   int sum = 0;
   sum += sizeof();
-  // 

[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-20 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/95550

From 06adc063c2388ea534537f5a417751fdf64b22cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Fri, 14 Jun 2024 15:16:34 +0200
Subject: [PATCH 1/2] [clang-tidy] Clarify diagnostics of
 bugprone-sizeof-expression

...becasue they were strangely worded and in a few cases outright
incorrect.
---
 .../bugprone/SizeofExpressionCheck.cpp| 22 ++---
 .../checkers/bugprone/sizeof-expression-2.c   | 12 +--
 .../sizeof-expression-any-pointer.cpp | 86 +--
 ...on-warn-on-sizeof-pointer-to-aggregate.cpp |  4 +-
 .../checkers/bugprone/sizeof-expression.cpp   | 84 +-
 5 files changed, 105 insertions(+), 103 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index c25ee42d0899a..3afa0e5c39882 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -296,7 +296,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   } else if (const auto *E =
  Result.Nodes.getNodeAs("sizeof-integer-call")) {
 diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
-   "that results in an integer")
+   "of integer type")
 << E->getSourceRange();
   } else if (const auto *E = Result.Nodes.getNodeAs("sizeof-this")) {
 diag(E->getBeginLoc(),
@@ -314,7 +314,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   << E->getSourceRange();
 } else {
   diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
- "that results in a pointer")
+ "of pointer type")
   << E->getSourceRange();
 }
   } else if (const auto *E = Result.Nodes.getNodeAs(
@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"
 " numerator is not a multiple of denominator")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
-" numerator is not a multiple of denominator")
+  diag(E->getOperatorLoc(),
+   "suspicious usage of 'sizeof(array)/sizeof(...)':"
+   " denominator differs from the size of array elements")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (NumTy && DenomTy && NumTy == DenomTy) {
-  // FIXME: This message is wrong, it should not refer to sizeof "pointer"
-  // usage (and by the way, it would be to clarify all the messages).
   diag(E->getOperatorLoc(),
-   "suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'")
+   "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+   "have the same type")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (!WarnOnSizeOfPointer) {
   // When 'WarnOnSizeOfPointer' is enabled, these messages become 
redundant:
   if (PointedTy && DenomTy && PointedTy == DenomTy) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': size of pointer "
+ "is divided by size of pointed type")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   } else if (NumTy && DenomTy && NumTy->isPointerType() &&
  DenomTy->isPointerType()) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+ "have pointer types")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   }
 }
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
index aef930f2c8fda..b898071a56613 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
@@ -34,24 +34,24 @@ int Test5() {
 
   int sum = 0;
   sum += sizeof();
-  // 

[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-20 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

@PiotrZSL I see, thanks for the explanation, the "colons may confuse parsers" 
question is a good point. I think I'll return to using semicolons, because 
that's what was used before my commit.

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-20 Thread Donát Nagy via cfe-commits


@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"

NagyDonat wrote:

I kept "usage of" and the apostrophes to be consistent with the rest of the 
messages emitted by this checker. If you think that this is important, it would 
be possible to extend the scope of this commit to apply these changes in all 
the other messages.

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-20 Thread Donát Nagy via cfe-commits


@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"
 " numerator is not a multiple of denominator")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
-" numerator is not a multiple of denominator")
+  diag(E->getOperatorLoc(),
+   "suspicious usage of 'sizeof(array)/sizeof(...)':"
+   " denominator differs from the size of array elements")

NagyDonat wrote:

Yes, this is only triggered when 
`arrayType(hasElementType(recordType().bind("elem-type")))` matches, so we have 
an array type whose elements are records.


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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-20 Thread Donát Nagy via cfe-commits


@@ -461,7 +446,7 @@ ProgramStateRef CStringChecker::checkInit(CheckerContext ,
   if (!ER)
 return State;
 
-  const TypedValueRegion *Orig = getOriginRegion(ER);
+  const auto *Orig = ER->getSuperRegion()->getAs();

NagyDonat wrote:

Nitpick: also change the name "`Orig`".

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,162 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SVB.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SVB.makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+ SizeTy)
+  .castAs();
+  SVal Offset =
+  SVB.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin region (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}
+
+// Basically 1 -> 1st, 12 -> 12th, etc.
+static void printIdxWithOrdinalSuffix(llvm::raw_ostream , unsigned Idx) {
+  Os << Idx << llvm::getOrdinalSuffix(Idx);

NagyDonat wrote:

```suggestion
  switch (Idx) {
case 1:
  Os << "first";
  break;
case 2:
  Os << "second";
  break;
case 3:
  Os << "third";
  break;
default:
  Os << Idx << llvm::getOrdinalSuffix(Idx);
  }
```
Consider printing "first", "second" and "third" instead of "1st", "2nd" and 
"3rd" because IMO it makes the diagnostics easier to read -- and this function 
will be used for argument indices in builtin functions, so these cases will be 
very common.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,162 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SVB.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SVB.makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+ SizeTy)
+  .castAs();
+  SVal Offset =
+  SVB.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin region (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}

NagyDonat wrote:

I thought several hours about this function, and my TLDR conclusion is that (1) 
this logic is wrong (2) `SymExpr::getOriginRegion()` is a red flag and (3) just 
use a plain `getSuperRegion()` call instead of this function. (Note that the 
branch where SymExpr::getOriginRegion() is used is not exercised in any 
testcase.)

More precisely, the problem is that `SymExpr::getOriginRegion()` is an 
extremely unnatural operation, which extracts a part of the "opaque unique tag" 
of the symbol. The result of `S->getOriginRegion()` is:
- the region _R_ when `S` is a `SymbolRegionValue` which represents "the value 
stored in the memory region _R_ at the start of the analysis of this function"
- the region _R_ when `S` is a `SymbolDerived` which represents "the value 
stored in the memory region _R_ after a certain invalidation"
- nullpointer in other cases (e.g. `SymbolConjured`).

As a concrete example, if you have a function like
```c++
void save_to_logs(int *src, int begin, int count) {
  memcpy(global_log_array, src + begin, count * sizeof(int));
}
```
then the element region representing `src + begin` would be passed to 
`getOriginRegion()`, which would first strip the `ElementRegion` layer to get a 
`SymbolicRegion`, then unwrap that to get a `SymbolRegionValue` and finally 
return the `ParamVarRegion` which represents the pointer-sized memory area of 
the variable `src`.

This won't lead to a crash because this `ParamVarRegion` is immediately 
discarded by the next check, which requires an array type:
```
if (!Orig->getValueType()->isArrayType())
return State;
```
However, there are no situations where `getOriginRegion()` = "region where a 
pointer to this symbolic region was stored at some earlier step" is actually 
useful, so you should just remove the branch using it.

By the way, I see that you need a `TypedValueRegion` after this point to 
continue the calculations -- but if the SuperRegion of your ElementRegion is a 
SymbolicRegion, then the right thing to do is just discarding it. A 
`SymbolicRegion` is not necessarily a real "region", it may just represent a 
pointer that points into the middle of some opaque unknown memory.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat requested changes to this pull request.

Thanks for the updates!

Unfortunately, as I dug deeper into your function `getOriginRegion()`, I 
realized that it is logically incorrect (see inline comment for explanation). 
(I was a bit suspicious during the earlier reviews as well, but this is a very 
complex area and earlier I didn't spend enough time on it.)

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-19 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}
+
+// Basically 1 -> 1st, 12 -> 12th, etc.
+static void printIdxWithOrdinalSuffix(llvm::raw_ostream , unsigned Idx) {
+  Os << Idx << llvm::getOrdinalSuffix(Idx);
+}
+
+ProgramStateRef CStringChecker::checkInit(CheckerContext ,
+  ProgramStateRef State,
+  AnyArgExpr Buffer, SVal Element,
+  SVal Size) const {
+
+  // If a previous check has failed, propagate the failure.
+  if (!State)
+return nullptr;
+
+  const MemRegion *R = Element.getAsRegion();
+  if (!R)
+return State;
+
+  const auto *ER = dyn_cast(R);
+  if (!ER)
+return State;
+
+  const TypedValueRegion *Orig = getOriginRegion(ER);
+  if (!Orig)
+return State;
+
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  // FIXME: We ought to able to check objects as well. Maybe
+  // UninitializedObjectChecker could help?
+  if (!Orig->getValueType()->isArrayType())
+return State;
+
+  const QualType ElemTy = Ctx.getBaseElementType(Orig->getValueType());
+  const NonLoc Zero = SValBuilder.makeZeroArrayIndex();
+
+  SVal FirstElementVal =
+  State->getLValue(ElemTy, Zero, loc::MemRegionVal(Orig)).castAs();
+  if (!isa(FirstElementVal))
+return State;
+
+  // Ensure that we wouldn't read uninitialized value.
+  if (Filter.CheckCStringUninitializedRead &&
+  State->getSVal(FirstElementVal.castAs()).isUndef()) {
+llvm::SmallString<258> Buf;
+llvm::raw_svector_ostream OS(Buf);
+OS << "The first element of the ";
+printIdxWithOrdinalSuffix(OS, Buffer.ArgumentIndex + 1);
+OS << " argument is undefined";
+emitUninitializedReadBug(C, State, Buffer.Expression, OS.str());
+return nullptr;
+  }
+
+  // We won't check whether the entire region is fully initialized -- lets just
+  // check that the first and the last element is. So, onto checking the last
+  // element:
+  const QualType IdxTy = SValBuilder.getArrayIndexType();
+
+  NonLoc ElemSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(ElemTy).getQuantity(), IdxTy)
+  .castAs();
+
+  // FIXME: Check that the size arg to the cstring function is divisible by
+  // size of the actual element type?
+
+  // The type of the argument to the cstring function is either char or wchar,
+  // but thats not the type of the original array (or memory region).
+  // Suppose the following:
+  //   int t[5];
+  //   memcpy(dst, t, sizeof(t) / sizeof(t[0]));
+  // When checking whether t is fully initialized, we see it as char array of
+  // size sizeof(int)*5. If we check the last element as a character, we read
+  // the last byte of an integer, which will be undefined. But just because
+  // that value is undefined, it doesn't mean that the element is 
uninitialized!
+  // For this reason, we need to retrieve the actual last element with the
+  // correct type.
+
+  // Divide the size argument to the cstring function by the actual element
+  // type. This value will be size of the array, or the index to the
+  // past-the-end element.
+  std::optional Offset =
+  SValBuilder
+  .evalBinOpNN(State, clang::BO_Div, Size.castAs(), ElemSize,
+   IdxTy)
+  .getAs();
+
+  // Retrieve the index of the last element.
+  const NonLoc One = SValBuilder.makeIntVal(1, IdxTy).castAs();
+  SVal LastIdx = SValBuilder.evalBinOpNN(State, BO_Sub, *Offset, One, IdxTy);
+
+  if 

[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-19 Thread Donát Nagy via cfe-commits

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-19 Thread Donát Nagy via cfe-commits


@@ -32,3 +32,20 @@ void different_2() {
   int d = p2 - p1; // expected-warning{{Subtraction of two pointers that do 
not point into the same array is undefined behavior}} \
// expected-note{{Subtraction of two pointers that do not 
point into the same array is undefined behavior}}
 }
+
+int different_3() {
+  struct {
+int array[5];
+  } a, b;
+  return [3] - [2]; // expected-warning{{Subtraction of two 
pointers that do not point into the same array is undefined behavior}} \
+// expected-note{{Subtraction of two 
pointers that do not point into the same array is undefined behavior}}
+}
+
+int different_5() {

NagyDonat wrote:

```suggestion
int different_4() {
```
Very minor nitpick: `different_3` was followed by `different_5`.

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-19 Thread Donát Nagy via cfe-commits


@@ -154,12 +154,14 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator 
*B,
 auto R =
 std::make_unique(BT, Msg_MemRegionDifferent, 
N);
 R->addRange(B->getSourceRange());
-if (DiffDeclL)
-  R->addNote("Array at the left-hand side of subtraction",
- {DiffDeclL, C.getSourceManager()});
-if (DiffDeclR)
-  R->addNote("Array at the right-hand side of subtraction",
- {DiffDeclR, C.getSourceManager()});
+if (DiffDeclL != DiffDeclR) {

NagyDonat wrote:

```suggestion
if (DiffDeclL != DiffDeclR) {
  // The declarations may be identical even if the regions are different,
  // if they are field regions within different objects:
  //   struct { int array[10]; } a, b;
  //   do_something_with(a.array[5] - b.array[5]);
  // In this case the notes would be confusing, so don't emit them.
```
Add a comment that explains this `if (DiffDeclL != DiffDeclR)` check because 
otherwise it would be very surprising.

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-19 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

LGTM, thanks for the update. I added two minor edit suggestions, but after that 
the commit can be merged.

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-19 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-18 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

If there is no feedback on the separator mark bikeshedding (which is 
understandable -- it's a very minor question), I'll merge this commit on 
Thursday.

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-18 Thread Donát Nagy via cfe-commits


@@ -144,9 +144,24 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator 
*B,
 // Allow arithmetic on different symbolic regions.
 if (isa(SuperLR) || isa(SuperRR))
   return;
+if (const auto *SuperDLR = dyn_cast(SuperLR))
+  DiffDeclL = SuperDLR->getDecl();
+if (const auto *SuperDRR = dyn_cast(SuperRR))
+  DiffDeclR = SuperDRR->getDecl();

NagyDonat wrote:

Note that `FieldRegion`s are `DeclRegion`s, so these declarations may be data 
member declarations within a `struct` or `class`. This is usually not a 
problem, but there is a corner case where `SuperLR != SuperRR`, but the 
corresponding declarations are identical:
```
struct {
  int array[5];
} a, b;
int func(void) {
  return [3] - [2];
}
```
In this case the current code would place both notes onto the declaration of 
`field`, which would be confusing for the user.

Consider adding some code that handles this situation explicitly. (Either 
simply skip note creation when `DiffDeclL == DiffDeclR`, or create a 
specialized note for this case.)

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-18 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat commented:

Looks good overall, I have one remark about a rare case that would require some 
specialized code.

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


[clang] [clang][analyzer] Add notes to PointerSubChecker (PR #95899)

2024-06-18 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-18 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}
+
+// Basically 1 -> 1st, 12 -> 12th, etc.
+static void printIdxWithOrdinalSuffix(llvm::raw_ostream , unsigned Idx) {
+  Os << Idx << llvm::getOrdinalSuffix(Idx);
+}
+
+ProgramStateRef CStringChecker::checkInit(CheckerContext ,
+  ProgramStateRef State,
+  AnyArgExpr Buffer, SVal Element,
+  SVal Size) const {
+
+  // If a previous check has failed, propagate the failure.
+  if (!State)
+return nullptr;
+
+  const MemRegion *R = Element.getAsRegion();
+  if (!R)
+return State;
+
+  const auto *ER = dyn_cast(R);
+  if (!ER)
+return State;
+
+  const TypedValueRegion *Orig = getOriginRegion(ER);
+  if (!Orig)
+return State;
+
+  SValBuilder  = State->getStateManager().getSValBuilder();

NagyDonat wrote:

I agree with both suggestions, `SVB` is the _right_ name mandated by our _holy 
traditions_.

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


[clang] [clang-tools-extra] Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (PR #95802)

2024-06-18 Thread Donát Nagy via cfe-commits


@@ -441,6 +441,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
   CASE( 4, 'e', 's', else);
   CASE( 4, 'l', 'n', line);
   CASE( 4, 's', 'c', sccs);
+  CASE(5, 'e', 'b', embed);

NagyDonat wrote:

```suggestion
  CASE( 5, 'e', 'b', embed);
```
Just drive-by bikeshedding -- consider aligning this like the lines around it.

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


[clang] [clang][analyzer] use unqualified canonical type during merging equivalence class (PR #95729)

2024-06-17 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

Nice catch, thanks for fixing this bug!

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-17 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

> Consider replacing ":" separator with ","

I switched to ":" (instead of the ";" that was used previously) to emphasize 
that the second part of the message is an explanation/reason for the first part 
(and not a second, separate issue). However I can switch to "," or ";" if that 
option turns out to be more popular.

@ rewiewers: Which symbol would you prefer in these messages?
(My preferences are dot > keep the semicolon ≳ comma.)

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


[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-14 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat created 
https://github.com/llvm/llvm-project/pull/95550

...becasue they were strangely worded and in a few cases outright incorrect.

From 06adc063c2388ea534537f5a417751fdf64b22cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Fri, 14 Jun 2024 15:16:34 +0200
Subject: [PATCH] [clang-tidy] Clarify diagnostics of
 bugprone-sizeof-expression

...becasue they were strangely worded and in a few cases outright
incorrect.
---
 .../bugprone/SizeofExpressionCheck.cpp| 22 ++---
 .../checkers/bugprone/sizeof-expression-2.c   | 12 +--
 .../sizeof-expression-any-pointer.cpp | 86 +--
 ...on-warn-on-sizeof-pointer-to-aggregate.cpp |  4 +-
 .../checkers/bugprone/sizeof-expression.cpp   | 84 +-
 5 files changed, 105 insertions(+), 103 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index c25ee42d0899a..3afa0e5c39882 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -296,7 +296,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   } else if (const auto *E =
  Result.Nodes.getNodeAs("sizeof-integer-call")) {
 diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
-   "that results in an integer")
+   "of integer type")
 << E->getSourceRange();
   } else if (const auto *E = Result.Nodes.getNodeAs("sizeof-this")) {
 diag(E->getBeginLoc(),
@@ -314,7 +314,7 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
   << E->getSourceRange();
 } else {
   diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
- "that results in a pointer")
+ "of pointer type")
   << E->getSourceRange();
 }
   } else if (const auto *E = Result.Nodes.getNodeAs(
@@ -342,31 +342,33 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 
 if (DenominatorSize > CharUnits::Zero() &&
 !NumeratorSize.isMultipleOf(DenominatorSize)) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
+  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)':"
 " numerator is not a multiple of denominator")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
-  diag(E->getOperatorLoc(), "suspicious usage of 
'sizeof(...)/sizeof(...)';"
-" numerator is not a multiple of denominator")
+  diag(E->getOperatorLoc(),
+   "suspicious usage of 'sizeof(array)/sizeof(...)':"
+   " denominator differs from the size of array elements")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (NumTy && DenomTy && NumTy == DenomTy) {
-  // FIXME: This message is wrong, it should not refer to sizeof "pointer"
-  // usage (and by the way, it would be to clarify all the messages).
   diag(E->getOperatorLoc(),
-   "suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'")
+   "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+   "have the same type")
   << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
 } else if (!WarnOnSizeOfPointer) {
   // When 'WarnOnSizeOfPointer' is enabled, these messages become 
redundant:
   if (PointedTy && DenomTy && PointedTy == DenomTy) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': size of pointer "
+ "is divided by size of pointed type")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   } else if (NumTy && DenomTy && NumTy->isPointerType() &&
  DenomTy->isPointerType()) {
 diag(E->getOperatorLoc(),
- "suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'")
+ "suspicious usage of 'sizeof(...)/sizeof(...)': both expressions "
+ "have pointer types")
 << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
   }
 }
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
index aef930f2c8fda..b898071a56613 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-2.c
@@ 

[clang-tools-extra] [clang-tidy] Clarify diagnostics of bugprone-sizeof-expression (PR #95550)

2024-06-14 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

This commit is motivated by the discussion on 
https://github.com/llvm/llvm-project/pull/94356 .

Feel free to bikeshed the messages, I'm not too attached to the new choices, 
I'm just unsatisfied with the old ones.

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-14 Thread Donát Nagy via cfe-commits


@@ -26,17 +28,10 @@ namespace {
 class Z3Config {

NagyDonat wrote:

If I understand it correctly, rule of three/five dictates that the copy/move 
assignment/construction of this class needs to be handled (or deleted).

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-14 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat commented:

I tried to review the resource management code thoroughly, but I admit that I'm 
not skilled in this area -- I'm used to working in modern C++ and Python where 
these footguns are less relevant.

I found two classed that (if I understand correctly) violate the "rule of 
three", but I didn't find any acute issues.

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-14 Thread Donát Nagy via cfe-commits


@@ -50,16 +45,17 @@ void Z3ErrorHandler(Z3_context Context, Z3_error_code 
Error) {
 /// Wrapper for Z3 context
 class Z3Context {

NagyDonat wrote:

Another class that manages a resource in a destructor, but does not handle 
copy/move assignment/construction.

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-14 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-14 Thread Donát Nagy via cfe-commits


@@ -413,38 +588,18 @@ ProgramStateRef 
CStringChecker::CheckLocation(CheckerContext ,
   if (!ER)
 return state;
 
-  SValBuilder  = C.getSValBuilder();
-  ASTContext  = svalBuilder.getContext();
-
   // Get the index of the accessed element.
-  NonLoc Idx = ER->getIndex();
-
-  if (CK == CharKind::Regular) {
-if (ER->getValueType() != Ctx.CharTy)
-  return state;
-  } else {
-if (ER->getValueType() != Ctx.WideCharTy)
-  return state;
-
-QualType SizeTy = Ctx.getSizeType();
-NonLoc WideSize =
-svalBuilder
-.makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
-SizeTy)
-.castAs();
-SVal Offset = svalBuilder.evalBinOpNN(state, BO_Mul, Idx, WideSize, 
SizeTy);
-if (Offset.isUnknown())
-  return state;
-Idx = Offset.castAs();
-  }
+  std::optional Idx = getIndex(state, ER, CK);
+  if (!Idx)
+return state;

NagyDonat wrote:

Consider capitalizing `state` in this function to be consistent with the coding 
guidelines and other functions.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-14 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat commented:

I read the rest of the commit and only found two very minor observations.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-14 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-14 Thread Donát Nagy via cfe-commits


@@ -26,16 +50,12 @@ void top(char *dst) {
 
 void *mempcpy(void *restrict s1, const void *restrict s2, size_t n);
 
-void mempcpy14() {
+void mempcpy13() {

NagyDonat wrote:

Why are you renaming this to `memcpy13`? I see only two `memcpy` tests after 
this and they have index 15 and 16, which is very random, but at least follows 
14 directly.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -413,38 +588,18 @@ ProgramStateRef 
CStringChecker::CheckLocation(CheckerContext ,
   if (!ER)
 return state;
 
-  SValBuilder  = C.getSValBuilder();
-  ASTContext  = svalBuilder.getContext();
-
   // Get the index of the accessed element.
-  NonLoc Idx = ER->getIndex();
-
-  if (CK == CharKind::Regular) {
-if (ER->getValueType() != Ctx.CharTy)
-  return state;
-  } else {
-if (ER->getValueType() != Ctx.WideCharTy)
-  return state;
-
-QualType SizeTy = Ctx.getSizeType();
-NonLoc WideSize =
-svalBuilder
-.makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
-SizeTy)
-.castAs();
-SVal Offset = svalBuilder.evalBinOpNN(state, BO_Mul, Idx, WideSize, 
SizeTy);
-if (Offset.isUnknown())
-  return state;
-Idx = Offset.castAs();
-  }
+  std::optional Idx = getIndex(state, ER, CK);
+  if (!Idx)
+return state;
 
   // Get the size of the array.
   const auto *superReg = cast(ER->getSuperRegion());
   DefinedOrUnknownSVal Size =
   getDynamicExtent(state, superReg, C.getSValBuilder());
 
   ProgramStateRef StInBound, StOutBound;
-  std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, Size);
+  std::tie(StInBound, StOutBound) = state->assumeInBoundDual(*Idx, Size);

NagyDonat wrote:

Perhaps apply a [structured 
binding](https://en.cppreference.com/w/cpp/language/structured_binding) instead 
of `std::tie`?

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}
+
+// Basically 1 -> 1st, 12 -> 12th, etc.
+static void printIdxWithOrdinalSuffix(llvm::raw_ostream , unsigned Idx) {
+  Os << Idx << llvm::getOrdinalSuffix(Idx);
+}
+
+ProgramStateRef CStringChecker::checkInit(CheckerContext ,
+  ProgramStateRef State,
+  AnyArgExpr Buffer, SVal Element,
+  SVal Size) const {
+
+  // If a previous check has failed, propagate the failure.
+  if (!State)
+return nullptr;
+
+  const MemRegion *R = Element.getAsRegion();
+  if (!R)
+return State;
+
+  const auto *ER = dyn_cast(R);
+  if (!ER)
+return State;
+
+  const TypedValueRegion *Orig = getOriginRegion(ER);
+  if (!Orig)
+return State;
+
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  // FIXME: We ought to able to check objects as well. Maybe
+  // UninitializedObjectChecker could help?
+  if (!Orig->getValueType()->isArrayType())
+return State;

NagyDonat wrote:

Perhaps move this above the definition of `SValBuilder` and `Ctx` to keep it 
together with all the other early return statements.

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

> Please have a second look at the llvm-related changes. Z3 has a really 
> dangerous C API. I shot myself in the foot literally 3 times while working on 
> this PR.

> And btw notice that I removed the proof=false configuration as that is the 
> default AFAIK, so that's why that is missing.

OK, I'll re-check the footgun handling either today or tomorrow.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();

NagyDonat wrote:

``
Please follow the convention that variable names start with a capital letter.
``

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),

NagyDonat wrote:

Normal person: "2"
Programmer: "`Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity()`"
;-)

(No action expected, we're programmers...)

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();
+  }
+  return dyn_cast_or_null(Ret);
+}
+
+// Basically 1 -> 1st, 12 -> 12th, etc.
+static void printIdxWithOrdinalSuffix(llvm::raw_ostream , unsigned Idx) {
+  Os << Idx << llvm::getOrdinalSuffix(Idx);
+}
+
+ProgramStateRef CStringChecker::checkInit(CheckerContext ,
+  ProgramStateRef State,
+  AnyArgExpr Buffer, SVal Element,
+  SVal Size) const {
+
+  // If a previous check has failed, propagate the failure.
+  if (!State)
+return nullptr;
+
+  const MemRegion *R = Element.getAsRegion();
+  if (!R)
+return State;
+
+  const auto *ER = dyn_cast(R);
+  if (!ER)
+return State;
+
+  const TypedValueRegion *Orig = getOriginRegion(ER);
+  if (!Orig)
+return State;
+
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  // FIXME: We ought to able to check objects as well. Maybe
+  // UninitializedObjectChecker could help?
+  if (!Orig->getValueType()->isArrayType())
+return State;
+
+  const QualType ElemTy = Ctx.getBaseElementType(Orig->getValueType());
+  const NonLoc Zero = SValBuilder.makeZeroArrayIndex();
+
+  SVal FirstElementVal =
+  State->getLValue(ElemTy, Zero, loc::MemRegionVal(Orig)).castAs();
+  if (!isa(FirstElementVal))
+return State;
+
+  // Ensure that we wouldn't read uninitialized value.
+  if (Filter.CheckCStringUninitializedRead &&
+  State->getSVal(FirstElementVal.castAs()).isUndef()) {
+llvm::SmallString<258> Buf;
+llvm::raw_svector_ostream OS(Buf);
+OS << "The first element of the ";
+printIdxWithOrdinalSuffix(OS, Buffer.ArgumentIndex + 1);
+OS << " argument is undefined";
+emitUninitializedReadBug(C, State, Buffer.Expression, OS.str());
+return nullptr;
+  }
+
+  // We won't check whether the entire region is fully initialized -- lets just
+  // check that the first and the last element is. So, onto checking the last
+  // element:
+  const QualType IdxTy = SValBuilder.getArrayIndexType();
+
+  NonLoc ElemSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(ElemTy).getQuantity(), IdxTy)
+  .castAs();
+
+  // FIXME: Check that the size arg to the cstring function is divisible by
+  // size of the actual element type?
+
+  // The type of the argument to the cstring function is either char or wchar,
+  // but thats not the type of the original array (or memory region).
+  // Suppose the following:
+  //   int t[5];
+  //   memcpy(dst, t, sizeof(t) / sizeof(t[0]));
+  // When checking whether t is fully initialized, we see it as char array of
+  // size sizeof(int)*5. If we check the last element as a character, we read
+  // the last byte of an integer, which will be undefined. But just because
+  // that value is undefined, it doesn't mean that the element is 
uninitialized!
+  // For this reason, we need to retrieve the actual last element with the
+  // correct type.
+
+  // Divide the size argument to the cstring function by the actual element
+  // type. This value will be size of the array, or the index to the
+  // past-the-end element.
+  std::optional Offset =
+  SValBuilder
+  .evalBinOpNN(State, clang::BO_Div, Size.castAs(), ElemSize,
+   IdxTy)
+  .getAs();
+
+  // Retrieve the index of the last element.
+  const NonLoc One = SValBuilder.makeIntVal(1, IdxTy).castAs();
+  SVal LastIdx = SValBuilder.evalBinOpNN(State, BO_Sub, *Offset, One, IdxTy);
+
+  if 

[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -413,38 +588,18 @@ ProgramStateRef 
CStringChecker::CheckLocation(CheckerContext ,
   if (!ER)
 return state;
 
-  SValBuilder  = C.getSValBuilder();
-  ASTContext  = svalBuilder.getContext();
-
   // Get the index of the accessed element.
-  NonLoc Idx = ER->getIndex();
-
-  if (CK == CharKind::Regular) {
-if (ER->getValueType() != Ctx.CharTy)
-  return state;
-  } else {
-if (ER->getValueType() != Ctx.WideCharTy)
-  return state;
-
-QualType SizeTy = Ctx.getSizeType();
-NonLoc WideSize =
-svalBuilder
-.makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
-SizeTy)
-.castAs();
-SVal Offset = svalBuilder.evalBinOpNN(state, BO_Mul, Idx, WideSize, 
SizeTy);
-if (Offset.isUnknown())
-  return state;
-Idx = Offset.castAs();
-  }
+  std::optional Idx = getIndex(state, ER, CK);
+  if (!Idx)
+return state;
 
   // Get the size of the array.
   const auto *superReg = cast(ER->getSuperRegion());
   DefinedOrUnknownSVal Size =
   getDynamicExtent(state, superReg, C.getSValBuilder());
 
   ProgramStateRef StInBound, StOutBound;
-  std::tie(StInBound, StOutBound) = state->assumeInBoundDual(Idx, Size);
+  std::tie(StInBound, StOutBound) = state->assumeInBoundDual(*Idx, Size);

NagyDonat wrote:

Consider using a structured binding instead of `std::tie`.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an
+// element region).
+static const TypedValueRegion *getOriginRegion(const ElementRegion *ER) {
+  const MemRegion *MR = ER->getSuperRegion();
+  const MemRegion *Ret = MR;
+  assert(MR);
+  if (const auto *sym = MR->getAs()) {
+SymbolRef sym2 = sym->getSymbol();
+if (!sym2)
+  return nullptr;
+Ret = sym2->getOriginRegion();
+  }
+  if (const auto *element = MR->getAs()) {
+Ret = element->getBaseRegion();

NagyDonat wrote:

This `getBaseRegion()` call could produce some surprising and inconsistent 
results: e.g. if you have
```
struct S {
  int field[20][20];
} array[10];
```
then calling `getOriginRegion` on the ElementRegion representing 
`array[5].field[3]` would return the FieldRegion representing `array[5].field`, 
but (if I understand this correctly) calling it on `array[5].field[3][6]` would 
return the NonParamVarRegion representing `array` because `getBaseRegion()` 
strips the FieldRegion layer.

Consider writing an explicit loop that only strips ElementRegion layers.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -393,6 +401,173 @@ ProgramStateRef 
CStringChecker::checkNonNull(CheckerContext ,
   return stateNonNull;
 }
 
+static std::optional getIndex(ProgramStateRef State,
+  const ElementRegion *ER, CharKind CK) {
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SValBuilder.getContext();
+
+  if (CK == CharKind::Regular) {
+if (ER->getValueType() != Ctx.CharTy)
+  return {};
+return ER->getIndex();
+  }
+
+  if (ER->getValueType() != Ctx.WideCharTy)
+return {};
+
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc WideSize =
+  SValBuilder
+  .makeIntVal(Ctx.getTypeSizeInChars(Ctx.WideCharTy).getQuantity(),
+  SizeTy)
+  .castAs();
+  SVal Offset =
+  SValBuilder.evalBinOpNN(State, BO_Mul, ER->getIndex(), WideSize, SizeTy);
+  if (Offset.isUnknown())
+return {};
+  return Offset.castAs();
+}
+
+// Try to get hold of the origin regin (e.g. the actual array region from an

NagyDonat wrote:

```suggestion
// Try to get hold of the origin region (e.g. the actual array region from an
```

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat commented:

Overall I'm satisfied with this commit, but I have some minor remarks.

I'm publishing some review comments now, but I'll continue the review tomorrow.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -26,16 +50,12 @@ void top(char *dst) {
 
 void *mempcpy(void *restrict s1, const void *restrict s2, size_t n);
 
-void mempcpy14() {
+void mempcpy13() {
   int src[] = {1, 2, 3, 4};
   int dst[5] = {0};
   int *p;
 
-  p = mempcpy(dst, src, 4 * sizeof(int)); // expected-warning{{Bytes string 
function accesses uninitialized/garbage values}}
-   // FIXME: This behaviour is actually surprising and needs to be fixed, 
-   // mempcpy seems to consider the very last byte of the src buffer 
uninitialized
-   // and returning undef unfortunately. It should have returned unknown or a 
conjured value instead.
-
+  p = mempcpy(dst, src, 4 * sizeof(int));
   clang_analyzer_eval(p == [4]); // no-warning (above is fatal)

NagyDonat wrote:

Delete or update the comment on this line.

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


[clang] [analyzer] Check the correct first and last elements in cstring.UninitializedRead (PR #95408)

2024-06-13 Thread Donát Nagy via cfe-commits

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -434,6 +447,12 @@ class SMTSolver {
   virtual bool isFPSupported() = 0;
 
   virtual void print(raw_ostream ) const = 0;
+
+  /// Sets the requested option.
+  virtual void setBoolParam(StringRef Key, bool Value) = 0;
+  virtual void setUnsignedParam(StringRef Key, unsigned Value) = 0;
+
+  virtual std::unique_ptr getStatistics() const = 0;

NagyDonat wrote:

> It's not used in this PR, and I find it difficult to add test for.
Ok, that's completely fine, it doesn't cause any problems here.

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits


@@ -434,6 +447,12 @@ class SMTSolver {
   virtual bool isFPSupported() = 0;
 
   virtual void print(raw_ostream ) const = 0;
+
+  /// Sets the requested option.
+  virtual void setBoolParam(StringRef Key, bool Value) = 0;
+  virtual void setUnsignedParam(StringRef Key, unsigned Value) = 0;
+
+  virtual std::unique_ptr getStatistics() const = 0;

NagyDonat wrote:

Is this method called anywhere?

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits

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


[clang] [llvm] [analyzer][NFC] Reorganize Z3 report refutation (PR #95128)

2024-06-13 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

LGTM. I didn't deeply analyze all the small details of the commit, but it is 
clearly NFC (builds better infrastructure for follow-up commits), the 
implementation is clear and elegant (slightly better quality than what I can 
write) and the tests demonstrate that it's working.

IMO feel free to merge this and continue with the next commit.

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


[clang] [analyzer] Finish moving alpha.core.SizeofPtr to clang-tidy (PR #95118)

2024-06-12 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Finish moving alpha.core.SizeofPtr to clang-tidy (PR #95118)

2024-06-12 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

> We should remember to mention this transfer explicitly in the release notes 
> one day.

Yes, I'll try to remember it. By the way, it is already mentioned in the 
clang-tidy release notes (apparently there the release notes are kept in sync 
with active development), but it's definitely important to mention this on the 
analyzer side as well. (This was just an alpha checker, so I suppose that there 
weren't too many users, but still.)

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


[clang-tools-extra] [clang-tidy] Improve sizeof(pointer) handling in bugprone-sizeof-expression (PR #94356)

2024-06-11 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

Minor correction: in the commit message I accidentally wrote 
`alpha.core.SizeofPointer` instead of `alpha.core.SizeofPtr`. (Fortunately this 
difference is mostly academical, because my followup commit will remove that 
checker.)

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


[clang] [analyzer] Finish moving alpha.core.SizeofPtr to clang-tidy (PR #95118)

2024-06-11 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat created 
https://github.com/llvm/llvm-project/pull/95118

The checker `alpha.core.SizeofPtr` was a very simple checker that did not rely 
on path sensitive analysis and was very similar to the (more complex and 
refined) clang-tidy check `bugprone-sizeof-expression`.

As there is no reason to maintain two separate implementations for the same 
goal (and clang-tidy is more lightweight and accessible than the Analyzer) I 
decided to move this functionality from the Static Analyzer to clang-tidy.

Recently my commit 546c816a529835a4cf89deecff957ea336a94fa2 reimplemented the 
advantageous parts of `alpha.core.SizeofPtr` within clang-tidy; now this commit 
finishes the transfer by deleting `alpha.core.SizeofPtr`.

From a168ee43267c83c2f59e3d8e8db746ecf62eb2ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Tue, 11 Jun 2024 15:42:27 +0200
Subject: [PATCH] [analyzer] Finish moving alpha.core.SizeofPtr to clang-tidy

The checker `alpha.core.SizeofPtr` was a very simple checker that did
not rely on path sensitive analysis and was very similar to the (more
complex and refined) clang-tidy check `bugprone-sizeof-expression`.

As there is no reason to maintain two separate implementations for the
same goal (and clang-tidy is more lightweight and accessible than the
Analyzer) I decided to move this functionality from the Static Analyzer
to clang-tidy.

Recently my commit 546c816a529835a4cf89deecff957ea336a94fa2
reimplemented the advantageous parts of `alpha.core.SizeofPtr` within
clang-tidy; now this commit finishes the transfer by deleting
`alpha.core.SizeofPtr`.
---
 clang/docs/analyzer/checkers.rst  | 15 ---
 .../clang/StaticAnalyzer/Checkers/Checkers.td |  4 -
 .../StaticAnalyzer/Checkers/CMakeLists.txt|  1 -
 .../Checkers/CheckSizeofPointer.cpp   | 96 ---
 clang/test/Analysis/sizeofpointer.c   |  8 --
 clang/www/analyzer/alpha_checks.html  | 16 
 6 files changed, 140 deletions(-)
 delete mode 100644 clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
 delete mode 100644 clang/test/Analysis/sizeofpointer.c

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index f53dd545df5a9..d76ee241da797 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2452,21 +2452,6 @@ Check for pointer subtractions on two pointers pointing 
to different memory chun
int d =  -  // warn
  }
 
-.. _alpha-core-SizeofPtr:
-
-alpha.core.SizeofPtr (C)
-
-Warn about unintended use of ``sizeof()`` on pointer expressions.
-
-.. code-block:: c
-
- struct s {};
-
- int test(struct s *p) {
-   return sizeof(p);
- // warn: sizeof(ptr) can produce an unexpected result
- }
-
 .. _alpha-core-StackAddressAsyncEscape:
 
 alpha.core.StackAddressAsyncEscape (C)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index a7f62ef7f2d07..429c334a0b24b 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -296,10 +296,6 @@ def PointerSubChecker : Checker<"PointerSub">,
"different memory chunks">,
   Documentation;
 
-def SizeofPointerChecker : Checker<"SizeofPtr">,
-  HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
-  Documentation;
-
 def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
   HelpText<"Check for division by variable that is later compared against 0. "
"Either the comparison is useless or there is division by zero.">,
diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt 
b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 68e829cace495..682cfa01bec96 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -24,7 +24,6 @@ add_clang_library(clangStaticAnalyzerCheckers
   CheckObjCInstMethSignature.cpp
   CheckPlacementNew.cpp
   CheckSecuritySyntaxOnly.cpp
-  CheckSizeofPointer.cpp
   CheckerDocumentation.cpp
   ChrootChecker.cpp
   CloneChecker.cpp
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp 
b/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
deleted file mode 100644
index 0d2551f11583e..0
--- a/clang/lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//==- CheckSizeofPointer.cpp - Check for sizeof on pointers --*- C++ 
-*-==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===--===//
-//
-//  This file defines a check for unintended use of sizeof() on pointer
-//  expressions.
-//

[clang-tools-extra] [clang-tidy] Improve sizeof(pointer) handling in bugprone-sizeof-expression (PR #94356)

2024-06-11 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Improve sizeof(pointer) handling in bugprone-sizeof-expression (PR #94356)

2024-06-11 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Improve sizeof(pointer) handling in bugprone-sizeof-expression (PR #94356)

2024-06-11 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-11 Thread Donát Nagy via cfe-commits

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


[clang] [clang] Remove a redundant check in Mangle. NFC (PR #95071)

2024-06-11 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.


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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-10 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

I evaluated the effects of the additional change [Generalize the suppression to 
all sizeof(array[0]) 
expressions](https://github.com/llvm/llvm-project/pull/94356/commits/ce3a37610228ceb9a9e60575f87886bf8e183493)
 compared to the earlier version of this PR, and it seems that this tweak 
eliminates a large amount of false positives:

| Project | New Reports | Resolved Reports |
|-|-|--|
| memcached | No reports | No reports 
| tmux | No reports | No reports 
| curl | No reports | [3 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=curl_curl-7_66_0_previous_sizeofexpression_after_most_changes=curl_curl-7_66_0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| twin | No reports | No reports 
| vim | No reports | No reports 
| openssl | No reports | [8 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=openssl_openssl-3.0.0-alpha7_previous_sizeofexpression_after_most_changes=openssl_openssl-3.0.0-alpha7_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| sqlite | No reports | [12 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=sqlite_version-3.33.0_previous_sizeofexpression_after_most_changes=sqlite_version-3.33.0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| ffmpeg | No reports | [9 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=ffmpeg_n4.3.1_previous_sizeofexpression_after_most_changes=ffmpeg_n4.3.1_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| postgres | No reports | [1 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=postgres_REL_13_0_previous_sizeofexpression_after_most_changes=postgres_REL_13_0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| tinyxml2 | No reports | No reports 
| libwebm | No reports | No reports 
| xerces | No reports | [10 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=xerces_v3.2.3_previous_sizeofexpression_after_most_changes=xerces_v3.2.3_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| bitcoin | No reports | [1 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=bitcoin_v0.20.1_previous_sizeofexpression_after_most_changes=bitcoin_v0.20.1_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| protobuf | No reports | [4 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=protobuf_v3.13.0_previous_sizeofexpression_after_most_changes=protobuf_v3.13.0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| qtbase | No reports | [7 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=qtbase_v6.2.0_previous_sizeofexpression_after_most_changes=qtbase_v6.2.0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 
| contour | No reports | No reports 
| openrct2 | No reports | No reports 
| llvm-project | No reports | [6 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=llvm-project_llvmorg-12.0.0_previous_sizeofexpression_after_most_changes=llvm-project_llvmorg-12.0.0_new_sizeofexpression_with_full_arrayindexzero_suppression=Resolved)
 

I randomly checked ~20% of the resolved reports, and they all were false 
positives (that is, situations where `sizeof(pointer)` is the idiomatic and 
correct solution), so I'm satisfied with this additional change.

At this point I'm satisfied with the behavior of this check on the real-world 
code and I'm not planning to add more features within this PR. (There is one 
known issue which I highlighted in a FIXME in commit [Extend 
GenericFunctionTest, document a class of FPs with a 
FIXME](https://github.com/llvm/llvm-project/pull/94356/commits/59bd1b83e4fa89b371f4d1a96c51fc7a1b4ad170)
 -- but that's significantly less severe than the issues before this PR, so I 
think it's enough to handle that later.) 

I also answered all the review suggestions, so I'd be grateful for another 
round of reviews from @PiotrZSL @EugeneZelenko or anybody else who has time for 
it.

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


[clang] [clang] Replace X && isa(X) with isa_and_nonnull(X). NFC (PR #94987)

2024-06-10 Thread Donát Nagy via cfe-commits


@@ -8510,7 +8510,8 @@ class MappableExprsHandler {
 assert(VDecl == VD && "We got information for the wrong 
declaration??");
 assert(!Components.empty() &&
"Not expecting declaration with no component lists.");
-if (VD && E && VD->getType()->isAnyPointerType() && 
isa(E))
+if (VD && VD->getType()->isAnyPointerType() &&
+isa_and_nonnull(E))
   HasMapBasePtr = true;
 if (VD && E && VD->getType()->isAnyPointerType() &&
 (isa(E) || isa(E)))

NagyDonat wrote:

Consider preserving the analogy between this and the next `if` with two 
analogous `isa<>()` calls.

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


[clang] [clang] Replace X && isa(X) with isa_and_nonnull(X). NFC (PR #94987)

2024-06-10 Thread Donát Nagy via cfe-commits


@@ -2772,7 +2772,7 @@ fixVariable(const VarDecl *VD, FixitStrategy::Kind K,
 // also covers call-operator of lamdas
 isa(FD) ||
 // skip when the function body is a try-block
-(FD->hasBody() && isa(FD->getBody())) ||
+isa_and_nonnull(FD->getBody()) ||

NagyDonat wrote:

The comment before the definition of `getBody()` says that
```
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid
/// unnecessary AST de-serialization of the body.
```
so perhaps it would be better to keep `hasBody()`. (Although I don't know 
whether performance is relevant at this point -- if we're handling an unusual 
case, then the runtime doesn't matter.)

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


[clang] [clang] Replace X && isa(X) with isa_and_nonnull(X). NFC (PR #94987)

2024-06-10 Thread Donát Nagy via cfe-commits

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


[clang] [clang] Replace X && isa(X) with isa_and_nonnull(X). NFC (PR #94987)

2024-06-10 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

LGTM as well, with two optional remarks.

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


[clang] [clang] Replace X && isa(X) with isa_and_nonnull(X). NFC (PR #94987)

2024-06-10 Thread Donát Nagy via cfe-commits


@@ -302,7 +302,7 @@ void MangleContext::mangleBlock(const DeclContext *DC, 
const BlockDecl *BD,
 assert((isa(DC) || isa(DC)) &&
"expected a NamedDecl or BlockDecl");
 if (isa(DC))
-  for (; DC && isa(DC); DC = DC->getParent())
+  for (; isa_and_nonnull(DC); DC = DC->getParent())
 (void) getBlockId(cast(DC), true);

NagyDonat wrote:

Could you remove the line `if (isa(DC))` as well? It's completely 
redundant with the loop condition.

Although I see that this is a big automatic change, so perhaps it should be 
left for a separate change.

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


[clang] [analyzer] Add an ownership change visitor to StreamChecker (PR #94957)

2024-06-10 Thread Donát Nagy via cfe-commits


@@ -168,8 +193,9 @@ REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, 
StreamState)
 namespace {
 
 class StreamChecker;
-using FnCheck = std::function;
+using FnCheckTy = void(const StreamChecker *, const FnDescription *,
+   const CallEvent &, CheckerContext &);
+using FnCheck = std::function;

NagyDonat wrote:

What is the goal of this change?

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


[clang] [analyzer] Add an ownership change visitor to StreamChecker (PR #94957)

2024-06-10 Thread Donát Nagy via cfe-commits

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


[clang] [analyzer] Add an ownership change visitor to StreamChecker (PR #94957)

2024-06-10 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

Nice improvement, LGTM overall. I only have one phrasing nitpick and one very 
minor question about a tangential change. 

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


[clang] [analyzer] Add an ownership change visitor to StreamChecker (PR #94957)

2024-06-10 Thread Donát Nagy via cfe-commits


@@ -696,6 +732,69 @@ struct StreamOperationEvaluator {
 
 } // end anonymous namespace
 
+//===--===//
+// Definition of NoStreamStateChangeVisitor.
+//===--===//
+
+namespace {
+class NoStreamStateChangeVisitor final : public NoOwnershipChangeVisitor {
+protected:
+  /// Syntactically checks whether the callee is a freeing function. Since
+  /// we have no path-sensitive information on this call (we would need a
+  /// CallEvent instead of a CallExpr for that), its possible that a
+  /// freeing function was called indirectly through a function pointer,
+  /// but we are not able to tell, so this is a best effort analysis.
+  bool isFreeingCallAsWritten(const CallExpr ) const {
+const auto *StreamChk = static_cast();
+if (StreamChk->FCloseDesc.matchesAsWritten(Call))
+  return true;
+
+return false;
+  }
+
+  bool doesFnIntendToHandleOwnership(const Decl *Callee,
+ ASTContext ) override {
+using namespace clang::ast_matchers;
+const FunctionDecl *FD = dyn_cast(Callee);
+
+auto Matches =
+match(findAll(callExpr().bind("call")), *FD->getBody(), ACtx);
+for (BoundNodes Match : Matches) {
+  if (const auto *Call = Match.getNodeAs("call"))
+if (isFreeingCallAsWritten(*Call))
+  return true;
+}
+// TODO: Ownership might change with an attempt to store stream object, not
+// only through freeing it. Check for attempted stores as well.
+return false;
+  }
+
+  virtual bool hasResourceStateChanged(ProgramStateRef CallEnterState,
+   ProgramStateRef CallExitEndState) final 
{
+return CallEnterState->get(Sym) !=
+   CallExitEndState->get(Sym);
+  }
+
+  PathDiagnosticPieceRef emitNote(const ExplodedNode *N) override {
+PathDiagnosticLocation L = PathDiagnosticLocation::create(
+N->getLocation(),
+N->getState()->getStateManager().getContext().getSourceManager());
+return std::make_shared(
+L, "Returning without freeing stream object or storing the pointer for 
"

NagyDonat wrote:

```suggestion
L, "Returning without freeing stream object or storing it for "
```
The current phrasing is technically correct, because the stream object is a 
`FILE *` _pointer_, but IMO "it" would be both shorter and easier to understand

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-10 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/94356

From c94feff726b48e7e3b5a46d5028cc5a6d0ac9beb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Wed, 22 May 2024 11:57:50 +0200
Subject: [PATCH 1/6] [clang-tidy] Add WarnOnSizeOfPointer mode to
 bugprone-sizeof-expression

This commit reimplements the functionality of the Clang Static Analyzer
checker `alpha.core.SizeofPointer` within clang-tidy by adding a new
(off-by-default) option to bugprone-sizeof-expression which activates
reporting all the `sizeof(ptr)` expressions (where ptr is an expression
that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer`
was an AST-based checker, which did not rely on the path sensitive
capabilities of the Static Analyzer, so there was no reason to keep it
in the Static Analyzer instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression,
because that check already provided several heuristics that reported
various especially suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't
surprise the existing users; but it can provide a more through coverage
for the vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than
the existing partial heuristics.

I preserved the exception that the RHS of an expression that looks like
`sizeof(array) / sizeof(array[0])` is not reported; and I added another
exception which ensures that `sizeof(*pp)` is not reported when `pp` is
a pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker
`alpha.core.SizeofPoionter` and I decided to copy it because it helped
to avoid several false positives on open-source code.

This commit also replaces the old message "suspicious usage of
'sizeof(A*)'; pointer to aggregate" with two more concrete messages; but
I feel that this tidy check would deserve a through cleanup of all the
diagnostic messages that it can produce. (I added a FIXME to mark one
outright misleading message.)
---
 .../bugprone/SizeofExpressionCheck.cpp|  95 ---
 .../bugprone/SizeofExpressionCheck.h  |   1 +
 .../checks/bugprone/sizeof-expression.rst |   5 +
 .../checkers/bugprone/sizeof-expression-2.c   |  12 +-
 .../sizeof-expression-any-pointer.cpp | 231 ++
 .../checkers/bugprone/sizeof-expression.cpp   |  63 +++--
 6 files changed, 351 insertions(+), 56 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-any-pointer.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 5e64d23874ec1..05ef666d4f01e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -67,7 +67,8 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
   WarnOnSizeOfCompareToConstant(
   Options.get("WarnOnSizeOfCompareToConstant", true)),
   WarnOnSizeOfPointerToAggregate(
-  Options.get("WarnOnSizeOfPointerToAggregate", true)) {}
+  Options.get("WarnOnSizeOfPointerToAggregate", true)),
+  WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)) {}
 
 void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -78,6 +79,7 @@ void 
SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
 WarnOnSizeOfCompareToConstant);
   Options.store(Opts, "WarnOnSizeOfPointerToAggregate",
 WarnOnSizeOfPointerToAggregate);
+  Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
 }
 
 void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -127,17 +129,30 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder 
*Finder) {
   const auto ConstStrLiteralDecl =
   varDecl(isDefinition(), hasType(hasCanonicalType(CharPtrType)),
   hasInitializer(ignoringParenImpCasts(stringLiteral(;
+  const auto VarWithConstStrLiteralDecl = expr(
+  hasType(hasCanonicalType(CharPtrType)),
+  ignoringParenImpCasts(declRefExpr(hasDeclaration(ConstStrLiteralDecl;
   Finder->addMatcher(
-  sizeOfExpr(has(ignoringParenImpCasts(
- expr(hasType(hasCanonicalType(CharPtrType)),
-  ignoringParenImpCasts(declRefExpr(
-  hasDeclaration(ConstStrLiteralDecl)))
+  sizeOfExpr(has(ignoringParenImpCasts(VarWithConstStrLiteralDecl)))
   .bind("sizeof-charp"),
   this);
 
-  // Detect sizeof(ptr) 

[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-07 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/94356

From c94feff726b48e7e3b5a46d5028cc5a6d0ac9beb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Wed, 22 May 2024 11:57:50 +0200
Subject: [PATCH 1/5] [clang-tidy] Add WarnOnSizeOfPointer mode to
 bugprone-sizeof-expression

This commit reimplements the functionality of the Clang Static Analyzer
checker `alpha.core.SizeofPointer` within clang-tidy by adding a new
(off-by-default) option to bugprone-sizeof-expression which activates
reporting all the `sizeof(ptr)` expressions (where ptr is an expression
that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer`
was an AST-based checker, which did not rely on the path sensitive
capabilities of the Static Analyzer, so there was no reason to keep it
in the Static Analyzer instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression,
because that check already provided several heuristics that reported
various especially suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't
surprise the existing users; but it can provide a more through coverage
for the vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than
the existing partial heuristics.

I preserved the exception that the RHS of an expression that looks like
`sizeof(array) / sizeof(array[0])` is not reported; and I added another
exception which ensures that `sizeof(*pp)` is not reported when `pp` is
a pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker
`alpha.core.SizeofPoionter` and I decided to copy it because it helped
to avoid several false positives on open-source code.

This commit also replaces the old message "suspicious usage of
'sizeof(A*)'; pointer to aggregate" with two more concrete messages; but
I feel that this tidy check would deserve a through cleanup of all the
diagnostic messages that it can produce. (I added a FIXME to mark one
outright misleading message.)
---
 .../bugprone/SizeofExpressionCheck.cpp|  95 ---
 .../bugprone/SizeofExpressionCheck.h  |   1 +
 .../checks/bugprone/sizeof-expression.rst |   5 +
 .../checkers/bugprone/sizeof-expression-2.c   |  12 +-
 .../sizeof-expression-any-pointer.cpp | 231 ++
 .../checkers/bugprone/sizeof-expression.cpp   |  63 +++--
 6 files changed, 351 insertions(+), 56 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-any-pointer.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 5e64d23874ec1..05ef666d4f01e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -67,7 +67,8 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
   WarnOnSizeOfCompareToConstant(
   Options.get("WarnOnSizeOfCompareToConstant", true)),
   WarnOnSizeOfPointerToAggregate(
-  Options.get("WarnOnSizeOfPointerToAggregate", true)) {}
+  Options.get("WarnOnSizeOfPointerToAggregate", true)),
+  WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)) {}
 
 void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -78,6 +79,7 @@ void 
SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
 WarnOnSizeOfCompareToConstant);
   Options.store(Opts, "WarnOnSizeOfPointerToAggregate",
 WarnOnSizeOfPointerToAggregate);
+  Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
 }
 
 void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -127,17 +129,30 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder 
*Finder) {
   const auto ConstStrLiteralDecl =
   varDecl(isDefinition(), hasType(hasCanonicalType(CharPtrType)),
   hasInitializer(ignoringParenImpCasts(stringLiteral(;
+  const auto VarWithConstStrLiteralDecl = expr(
+  hasType(hasCanonicalType(CharPtrType)),
+  ignoringParenImpCasts(declRefExpr(hasDeclaration(ConstStrLiteralDecl;
   Finder->addMatcher(
-  sizeOfExpr(has(ignoringParenImpCasts(
- expr(hasType(hasCanonicalType(CharPtrType)),
-  ignoringParenImpCasts(declRefExpr(
-  hasDeclaration(ConstStrLiteralDecl)))
+  sizeOfExpr(has(ignoringParenImpCasts(VarWithConstStrLiteralDecl)))
   .bind("sizeof-charp"),
   this);
 
-  // Detect sizeof(ptr) 

[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-07 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

I re-ran the open source evaluation, and here is the clean diff that I promised 
(italicized notes are just copied from the old table):

| Project | New Reports | Resolved Reports | Notes 
|-|-|--|--|
| memcached | No reports | No reports | –
| tmux | No reports | [23 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=tmux_2.6_old_sizeofexpressions_with_new_messages=tmux_2.6_new_sizeofexpressions_rerun=Resolved)
 | _reports seem to be FPs, including several ones that [use `qsort` in a clear 
and straightforward 
way](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=tmux_2.6_old_sizeofexpressions=tmux_2.6_new_sizeofexpressions=Resolved=5493278=e1dd82bffcf68169ff8fe7181ca44f16=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Ftmux%2Fwindow-buffer.c)_
| curl | [3 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=curl_curl-7_66_0_old_sizeofexpressions_with_new_messages=curl_curl-7_66_0_new_sizeofexpressions_rerun=New)
 | [1 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=curl_curl-7_66_0_old_sizeofexpressions_with_new_messages=curl_curl-7_66_0_new_sizeofexpressions_rerun=Resolved)
 | _new reports are TPs (all reporting incorrect use of the same data 
structure), resolved one is FP_
| twin | No reports | No reports | – 
| vim | [1 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=vim_v8.2.1920_old_sizeofexpressions_with_new_messages=vim_v8.2.1920_new_sizeofexpressions_rerun=New)
 | No reports | _true positive_
| openssl | [23 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=openssl_openssl-3.0.0-alpha7_old_sizeofexpressions_with_new_messages_openssl_ffmpeg=openssl_openssl-3.0.0-alpha7_new_sizeofexpressions_rerun_openssl_ffmpeg=New)
 | [22 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=openssl_openssl-3.0.0-alpha7_old_sizeofexpressions_with_new_messages_openssl_ffmpeg=openssl_openssl-3.0.0-alpha7_new_sizeofexpressions_rerun_openssl_ffmpeg=Resolved)
 | resolved reports are FPs, new reports are mostly TPs or "works, but ugly and 
dodgy" code with a few FPs that look like `generic_function(, sizeof(arg))` 
or `get_memory(length*sizeof(array[0]))`
| sqlite | [11 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=sqlite_version-3.33.0_old_sizeofexpressions_with_new_messages=sqlite_version-3.33.0_new_sizeofexpressions_rerun=New)
 | No reports | _among the new results there are many FPs 
([(1)](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=New=5493379=f411835e93b1711c2889d4bef2889db9=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Fsqlite%2Fshell.c),
 
[(2)](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=New=5493385=d9e3d0a984913130c821b7c18c2cc8d2=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Fsqlite%2Fsqlite3.c))
 that do things like `char **mem; realloc(mem, numElements*sizeof(mem[0]))`_
| ffmpeg | [22 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=ffmpeg_n4.3.1_old_sizeofexpressions_with_new_messages_openssl_ffmpeg=ffmpeg_n4.3.1_new_sizeofexpressions_rerun_openssl_ffmpeg=New)
 | [109 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=ffmpeg_n4.3.1_old_sizeofexpressions_with_new_messages_openssl_ffmpeg=ffmpeg_n4.3.1_new_sizeofexpressions_rerun_openssl_ffmpeg=Resolved)
 
| postgres | No reports | [5 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=postgres_REL_13_0_old_sizeofexpressions_with_new_messages=postgres_REL_13_0_new_sizeofexpressions_rerun=Resolved)
 | _resolved reports are FPs_
| tinyxml2 | No reports | No reports  | –
| libwebm | No reports | No reports  | –
| xerces | [1 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=xerces_v3.2.3_old_sizeofexpressions_with_new_messages=xerces_v3.2.3_new_sizeofexpressions_rerun=New)
 | No reports | true positive, seems to be an ugly bug
| bitcoin | [1 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=bitcoin_v0.20.1_old_sizeofexpressions_with_new_messages=bitcoin_v0.20.1_new_sizeofexpressions_rerun=New)
 | No reports | false positive `hasher.Write((const unsigned char*), 
sizeof(ptr));`
| protobuf | [5 new 

[clang] [analyzer][NFC] Factor out NoOwnershipChangeVisitor (PR #94357)

2024-06-06 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.


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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-06 Thread Donát Nagy via cfe-commits


@@ -190,6 +190,15 @@ Options
 
 .. option:: WarnOnSizeOfPointerToAggregate
 
-   When `true`, the check will warn on an expression like
-   ``sizeof(expr)`` where the expression is a pointer
-   to aggregate. Default is `true`.
+   When `true`, the check will warn when the argument of ``sizeof`` is either a
+   pointer-to-aggregate type, an expression returning a pointer-to-aggregate
+   value or an expression that returns a pointer from an array-to-pointer
+   conversion (that may be implicit or explicit, for example ``array + 2`` or
+   ``(int *)array``). Default is `true`.

NagyDonat wrote:

I also added a proper description for `WarnOnSizeOfPointerToAggregate`, because 
the old one was very vague and didn't explain the (somewhat complex) effects 
that are handled here.

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-06 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/94356

From c94feff726b48e7e3b5a46d5028cc5a6d0ac9beb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Wed, 22 May 2024 11:57:50 +0200
Subject: [PATCH 1/3] [clang-tidy] Add WarnOnSizeOfPointer mode to
 bugprone-sizeof-expression

This commit reimplements the functionality of the Clang Static Analyzer
checker `alpha.core.SizeofPointer` within clang-tidy by adding a new
(off-by-default) option to bugprone-sizeof-expression which activates
reporting all the `sizeof(ptr)` expressions (where ptr is an expression
that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer`
was an AST-based checker, which did not rely on the path sensitive
capabilities of the Static Analyzer, so there was no reason to keep it
in the Static Analyzer instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression,
because that check already provided several heuristics that reported
various especially suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't
surprise the existing users; but it can provide a more through coverage
for the vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than
the existing partial heuristics.

I preserved the exception that the RHS of an expression that looks like
`sizeof(array) / sizeof(array[0])` is not reported; and I added another
exception which ensures that `sizeof(*pp)` is not reported when `pp` is
a pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker
`alpha.core.SizeofPoionter` and I decided to copy it because it helped
to avoid several false positives on open-source code.

This commit also replaces the old message "suspicious usage of
'sizeof(A*)'; pointer to aggregate" with two more concrete messages; but
I feel that this tidy check would deserve a through cleanup of all the
diagnostic messages that it can produce. (I added a FIXME to mark one
outright misleading message.)
---
 .../bugprone/SizeofExpressionCheck.cpp|  95 ---
 .../bugprone/SizeofExpressionCheck.h  |   1 +
 .../checks/bugprone/sizeof-expression.rst |   5 +
 .../checkers/bugprone/sizeof-expression-2.c   |  12 +-
 .../sizeof-expression-any-pointer.cpp | 231 ++
 .../checkers/bugprone/sizeof-expression.cpp   |  63 +++--
 6 files changed, 351 insertions(+), 56 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-any-pointer.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 5e64d23874ec1..05ef666d4f01e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -67,7 +67,8 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
   WarnOnSizeOfCompareToConstant(
   Options.get("WarnOnSizeOfCompareToConstant", true)),
   WarnOnSizeOfPointerToAggregate(
-  Options.get("WarnOnSizeOfPointerToAggregate", true)) {}
+  Options.get("WarnOnSizeOfPointerToAggregate", true)),
+  WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)) {}
 
 void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -78,6 +79,7 @@ void 
SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
 WarnOnSizeOfCompareToConstant);
   Options.store(Opts, "WarnOnSizeOfPointerToAggregate",
 WarnOnSizeOfPointerToAggregate);
+  Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
 }
 
 void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -127,17 +129,30 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder 
*Finder) {
   const auto ConstStrLiteralDecl =
   varDecl(isDefinition(), hasType(hasCanonicalType(CharPtrType)),
   hasInitializer(ignoringParenImpCasts(stringLiteral(;
+  const auto VarWithConstStrLiteralDecl = expr(
+  hasType(hasCanonicalType(CharPtrType)),
+  ignoringParenImpCasts(declRefExpr(hasDeclaration(ConstStrLiteralDecl;
   Finder->addMatcher(
-  sizeOfExpr(has(ignoringParenImpCasts(
- expr(hasType(hasCanonicalType(CharPtrType)),
-  ignoringParenImpCasts(declRefExpr(
-  hasDeclaration(ConstStrLiteralDecl)))
+  sizeOfExpr(has(ignoringParenImpCasts(VarWithConstStrLiteralDecl)))
   .bind("sizeof-charp"),
   this);
 
-  // Detect sizeof(ptr) 

[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-06 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-06 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat updated 
https://github.com/llvm/llvm-project/pull/94356

From c94feff726b48e7e3b5a46d5028cc5a6d0ac9beb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Wed, 22 May 2024 11:57:50 +0200
Subject: [PATCH 1/2] [clang-tidy] Add WarnOnSizeOfPointer mode to
 bugprone-sizeof-expression

This commit reimplements the functionality of the Clang Static Analyzer
checker `alpha.core.SizeofPointer` within clang-tidy by adding a new
(off-by-default) option to bugprone-sizeof-expression which activates
reporting all the `sizeof(ptr)` expressions (where ptr is an expression
that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer`
was an AST-based checker, which did not rely on the path sensitive
capabilities of the Static Analyzer, so there was no reason to keep it
in the Static Analyzer instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression,
because that check already provided several heuristics that reported
various especially suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't
surprise the existing users; but it can provide a more through coverage
for the vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than
the existing partial heuristics.

I preserved the exception that the RHS of an expression that looks like
`sizeof(array) / sizeof(array[0])` is not reported; and I added another
exception which ensures that `sizeof(*pp)` is not reported when `pp` is
a pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker
`alpha.core.SizeofPoionter` and I decided to copy it because it helped
to avoid several false positives on open-source code.

This commit also replaces the old message "suspicious usage of
'sizeof(A*)'; pointer to aggregate" with two more concrete messages; but
I feel that this tidy check would deserve a through cleanup of all the
diagnostic messages that it can produce. (I added a FIXME to mark one
outright misleading message.)
---
 .../bugprone/SizeofExpressionCheck.cpp|  95 ---
 .../bugprone/SizeofExpressionCheck.h  |   1 +
 .../checks/bugprone/sizeof-expression.rst |   5 +
 .../checkers/bugprone/sizeof-expression-2.c   |  12 +-
 .../sizeof-expression-any-pointer.cpp | 231 ++
 .../checkers/bugprone/sizeof-expression.cpp   |  63 +++--
 6 files changed, 351 insertions(+), 56 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-any-pointer.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
index 5e64d23874ec1..05ef666d4f01e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -67,7 +67,8 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
   WarnOnSizeOfCompareToConstant(
   Options.get("WarnOnSizeOfCompareToConstant", true)),
   WarnOnSizeOfPointerToAggregate(
-  Options.get("WarnOnSizeOfPointerToAggregate", true)) {}
+  Options.get("WarnOnSizeOfPointerToAggregate", true)),
+  WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)) {}
 
 void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -78,6 +79,7 @@ void 
SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap ) {
 WarnOnSizeOfCompareToConstant);
   Options.store(Opts, "WarnOnSizeOfPointerToAggregate",
 WarnOnSizeOfPointerToAggregate);
+  Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
 }
 
 void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
@@ -127,17 +129,30 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder 
*Finder) {
   const auto ConstStrLiteralDecl =
   varDecl(isDefinition(), hasType(hasCanonicalType(CharPtrType)),
   hasInitializer(ignoringParenImpCasts(stringLiteral(;
+  const auto VarWithConstStrLiteralDecl = expr(
+  hasType(hasCanonicalType(CharPtrType)),
+  ignoringParenImpCasts(declRefExpr(hasDeclaration(ConstStrLiteralDecl;
   Finder->addMatcher(
-  sizeOfExpr(has(ignoringParenImpCasts(
- expr(hasType(hasCanonicalType(CharPtrType)),
-  ignoringParenImpCasts(declRefExpr(
-  hasDeclaration(ConstStrLiteralDecl)))
+  sizeOfExpr(has(ignoringParenImpCasts(VarWithConstStrLiteralDecl)))
   .bind("sizeof-charp"),
   this);
 
-  // Detect sizeof(ptr) 

[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-06 Thread Donát Nagy via cfe-commits


@@ -292,11 +318,17 @@ void SizeofExpressionCheck::check(const 
MatchFinder::MatchResult ) {
 diag(E->getBeginLoc(),
  "suspicious usage of 'sizeof(char*)'; do you mean 'strlen'?")
 << E->getSourceRange();
-  } else if (const auto *E =
- Result.Nodes.getNodeAs("sizeof-pointer-to-aggregate")) {
-diag(E->getBeginLoc(),
- "suspicious usage of 'sizeof(A*)'; pointer to aggregate")
-<< E->getSourceRange();
+  } else if (const auto *E = Result.Nodes.getNodeAs("sizeof-pointer")) {
+if (Result.Nodes.getNodeAs("struct-type")) {
+  diag(E->getBeginLoc(),
+   "suspicious usage of 'sizeof(A*)' on pointer-to-aggregate type; did 
"
+   "you mean 'sizeof(A)'?")
+  << E->getSourceRange();
+} else {
+  diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
+ "that results in a pointer")

NagyDonat wrote:

I used this phrasing to be consistent with the analogous message "suspicious 
usage of 'sizeof()' on an expression that results in an integer". I would also 
prefer "suspicious use of 'sizeof()' on an expression of pointer type", but 
then it would be good to update the message for integers, and then it would be 
good to update all the other awkward messages printed by this check...

I'd prefer to keep the current consistent and (IMO) barely acceptable message 
in this commit; and leave a general cleanup of all the messages of this checker 
for a separate followup commit. (I'm not very enthusiastic for doing this 
cleanup, but I can do it if the community feels that it would be important.)

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


[clang] [analyzer][NFC] Factor out NoOwnershipChangeVisitor (PR #94357)

2024-06-06 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

Perfectly normal NFC change, feel free to merge it (assuming that the tests 
pass).

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-05 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

I analyzed several open source project with this check to observe the effects 
of my commit and I was (pleasantly?) surprised to see that it detected some 
ugly errors (despite the fact that the inputs are stable open source 
projects...).

The following table compares the "old" state before this commit and the "new" 
state where this commit is active and the freshly added option 
`WarnOnSizeOfPointer` is set to true (instead of the default "false"):
| Project | New Reports | Resolved Reports | Notes | 
|-|-|--|---|
| memcached | No reports | No reports | – 
| tmux | No reports | [23 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=tmux_2.6_old_sizeofexpressions=tmux_2.6_new_sizeofexpressions=Resolved)
 | reports seem to be FPs, including several ones that [use `qsort` in a clear 
and straightforward 
way](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=tmux_2.6_old_sizeofexpressions=tmux_2.6_new_sizeofexpressions=Resolved=5493278=e1dd82bffcf68169ff8fe7181ca44f16=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Ftmux%2Fwindow-buffer.c)
| curl | [3 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=curl_curl-7_66_0_old_sizeofexpressions=curl_curl-7_66_0_new_sizeofexpressions=New)
 | [1 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=curl_curl-7_66_0_old_sizeofexpressions=curl_curl-7_66_0_new_sizeofexpressions=Resolved)
 | new reports are TPs (all reporting incorrect use of the same data 
structure), resolved one is FP
| twin | No reports | No reports | –
| vim | [1 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=vim_v8.2.1920_old_sizeofexpressions=vim_v8.2.1920_new_sizeofexpressions=New)
 | No reports | true positive 
| openssl | [33 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=openssl_openssl-3.0.0-alpha7_old_sizeofexpressions=openssl_openssl-3.0.0-alpha7_new_sizeofexpressions=New)
 | [32 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=openssl_openssl-3.0.0-alpha7_old_sizeofexpressions=openssl_openssl-3.0.0-alpha7_new_sizeofexpressions=Resolved)
 | ...
| sqlite | [19 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=New)
 | [8 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=Resolved)
 | among the new results there are many FPs 
([(1)](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=New=5493379=f411835e93b1711c2889d4bef2889db9=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Fsqlite%2Fshell.c),
 
[(2)](https://codechecker-demo.eastus.cloudapp.azure.com/Default/report-detail?run=sqlite_version-3.33.0_old_sizeofexpressions=sqlite_version-3.33.0_new_sizeofexpressions=New=5493385=d9e3d0a984913130c821b7c18c2cc8d2=%2Flocal%2Fpersistent_docker%2FCSA-measurements-driver-2894%2Fmeasurements_workspace%2Fsqlite%2Fsqlite3.c))
 that do things like `char **mem; realloc(mem, numElements*sizeof(mem[0]))`; 
the resolved reports are FPs and they reappear among the new reports with a 
different message
| ffmpeg | [31 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=ffmpeg_n4.3.1_old_sizeofexpressions=ffmpeg_n4.3.1_new_sizeofexpressions=New)
 | [118 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=ffmpeg_n4.3.1_old_sizeofexpressions=ffmpeg_n4.3.1_new_sizeofexpressions=Resolved)
 | ...
| postgres | [2 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=postgres_REL_13_0_old_sizeofexpressions=postgres_REL_13_0_new_sizeofexpressions=New)
 | [7 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=postgres_REL_13_0_old_sizeofexpressions=postgres_REL_13_0_new_sizeofexpressions=Resolved)
 | resolved reports are mostly FPs, two of them (one FP + one "technically 
works, but stupid" code) reappear as "new" reports with the new message
| tinyxml2 | [1 new 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=tinyxml2_8.0.0_old_sizeofexpressions=tinyxml2_8.0.0_new_sizeofexpressions=New)
 | [1 resolved 
reports](https://codechecker-demo.eastus.cloudapp.azure.com/Default/reports?run=tinyxml2_8.0.0_old_sizeofexpressions=tinyxml2_8.0.0_new_sizeofexpressions=Resolved)
  | same FP is reported with the new message
| libwebm | No reports | No reports | –
| xerces | [16 new 

[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-05 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

@EugeneZelenko Thanks for inviting some additional reviewers. I'll add an entry 
in the release notes.

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-04 Thread Donát Nagy via cfe-commits

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-04 Thread Donát Nagy via cfe-commits


@@ -124,8 +124,6 @@ int Test1(const char* ptr) {
   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof 
pointer 'sizeof(P*)/sizeof(Q*)'
   sum += sizeof(ptr) / sizeof(char);
   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof 
pointer 'sizeof(T*)/sizeof(T)'
-  sum += sizeof(ptr) / sizeof(ptr[0]);
-  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof 
pointer 'sizeof(T*)/sizeof(T)'

NagyDonat wrote:

I'm deleting this test line, because the same expression also appears on line 
117.

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


[clang-tools-extra] [clang-tidy] Add WarnOnSizeOfPointer mode to bugprone-sizeof-expression (PR #94356)

2024-06-04 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat created 
https://github.com/llvm/llvm-project/pull/94356

This commit reimplements the functionality of the Clang Static Analyzer checker 
`alpha.core.SizeofPointer` within clang-tidy by adding a new (off-by-default) 
option to bugprone-sizeof-expression which activates reporting all the 
`sizeof(ptr)` expressions (where ptr is an expression that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer` was an 
AST-based checker, which did not rely on the path sensitive capabilities of the 
Static Analyzer, so there was no reason to keep it in the Static Analyzer 
instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes 
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression, because 
that check already provided several heuristics that reported various especially 
suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't surprise the 
existing users; but it can provide a more through coverage for the 
vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than the existing 
partial heuristics.

I preserved the exception that the RHS of an expression that looks like 
`sizeof(array) / sizeof(array[0])` is not reported; and I added another 
exception which ensures that `sizeof(*pp)` is not reported when `pp` is a 
pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode 
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker 
`alpha.core.SizeofPoionter` and I decided to copy it because it helped to avoid 
several false positives on open-source code.

This commit also replaces the old message "suspicious usage of 'sizeof(A*)'; 
pointer to aggregate" with two more concrete messages; but I feel that this 
tidy check would deserve a through cleanup of all the diagnostic messages that 
it can produce. (I added a FIXME to mark one outright misleading message.)

From c94feff726b48e7e3b5a46d5028cc5a6d0ac9beb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= 
Date: Wed, 22 May 2024 11:57:50 +0200
Subject: [PATCH] [clang-tidy] Add WarnOnSizeOfPointer mode to
 bugprone-sizeof-expression

This commit reimplements the functionality of the Clang Static Analyzer
checker `alpha.core.SizeofPointer` within clang-tidy by adding a new
(off-by-default) option to bugprone-sizeof-expression which activates
reporting all the `sizeof(ptr)` expressions (where ptr is an expression
that produces a pointer).

The main motivation for this change is that `alpha.core.SizeofPointer`
was an AST-based checker, which did not rely on the path sensitive
capabilities of the Static Analyzer, so there was no reason to keep it
in the Static Analyzer instead of the more lightweight clang-tidy.

After this commit I'm planning to create a separate commit that deletes
`alpha.core.SizeofPointer` from Clang Static Analyzer.

It was natural to place this moved logic in bugprone-sizeof-expression,
because that check already provided several heuristics that reported
various especially suspicious classes of `sizeof(ptr)` expressions.

The new mode `WarnOnSizeOfPointer` is off-by-default, so it won't
surprise the existing users; but it can provide a more through coverage
for the vulnerability CWE-467 ("Use of sizeof() on a Pointer Type") than
the existing partial heuristics.

I preserved the exception that the RHS of an expression that looks like
`sizeof(array) / sizeof(array[0])` is not reported; and I added another
exception which ensures that `sizeof(*pp)` is not reported when `pp` is
a pointer-to-pointer expression.

This second exception (which I also apply in the "old" on-by-default mode
`WarnOnSizeOfPointerToAggregate`) was present in the CSA checker
`alpha.core.SizeofPoionter` and I decided to copy it because it helped
to avoid several false positives on open-source code.

This commit also replaces the old message "suspicious usage of
'sizeof(A*)'; pointer to aggregate" with two more concrete messages; but
I feel that this tidy check would deserve a through cleanup of all the
diagnostic messages that it can produce. (I added a FIXME to mark one
outright misleading message.)
---
 .../bugprone/SizeofExpressionCheck.cpp|  95 ---
 .../bugprone/SizeofExpressionCheck.h  |   1 +
 .../checks/bugprone/sizeof-expression.rst |   5 +
 .../checkers/bugprone/sizeof-expression-2.c   |  12 +-
 .../sizeof-expression-any-pointer.cpp | 231 ++
 .../checkers/bugprone/sizeof-expression.cpp   |  63 +++--
 6 files changed, 351 insertions(+), 56 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-any-pointer.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp

[clang] [analyzer] New optin.taint.TaintAlloc checker for catching unbounded memory allocation calls (PR #92420)

2024-06-03 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

The change LGTM. I agree with @steakhal that `TaintedAlloc` would be a slightly 
better name, but the current one is also acceptable.

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


[clang] [clang][analyzer] Improved PointerSubChecker (PR #93676)

2024-06-03 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

> With the current version I have the following observations:
> 
> * There is a warning for `( + 1) - ` and `( - 1) - `. Should this 
> be fixed?

The expression `( + 1) - ` is valid and should not produce a warning. It 
could appear e.g. in code that's structured like
```
void log_observations(double *begin, double *end, /*...*/) {
  log_observation_count(end - begin);
  // also log the actual observations
}
void do_observations(/*...*/) {
  double array[1024], *p = array;
  //...
  while (can_observe()) {
*p++ = /* ... */
  }
  log_observations(array, p);
}
void do_single_observation(/*...*/) {
  if (!can_observe())
return;
  double result = /* ... */
  // ...
  log_observations(,  + 1);
}
```

On the other hand `( - 1) - ` is not standard-compliant, because the 
standard guarantees an "after-the-end" pointer (which is valid in calculations 
but must not be dereferenced) but it doesn't accept a "before-the-begin" 
pointer.

> * The code `(int *)((char *)([4]) + sizeof(int)) - [4]` produces no 
> warning but `(int *)((char *)([4]) + 1) - [4]` produces warning.

That's very nice, even a slightly less accurate solution would be acceptable.

> For 2-dimensional arrays there is warning for all of these cases (lines 44-47 
> in the test file). Is this possible to fix (to get warning in all cases), or 
> no warning is needed here?

I'd say that the current behavior (warning on all of 44-47) is OK here -- this 
is very unusual trickery and deserves a highlight. However I could also accept 
a situation where there was no warning for these complex multidimensional cases.

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


[clang] [clang][analyzer] Improved PointerSubChecker (PR #93676)

2024-06-03 Thread Donát Nagy via cfe-commits


@@ -0,0 +1,74 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.PointerSub -verify %s
+
+void f1(void) {
+  int x, y, z[10];
+  int d =  -  // expected-warning{{Subtraction of two pointers that do 
not point into the same array is undefined behavior}}
+  d = z -  // expected-warning{{Subtraction of two pointers that do not 
point into the same array is undefined behavior}}
+  d =  -  // expected-warning{{Subtraction of two pointers that do not 
point into the same array is undefined behavior}}
+  d = (long*) - (long*)
+}
+
+void f2(void) {
+  int a[10], b[10], c;
+  int *p = [2];
+  int *q = [8];
+  int d = q - p; // no-warning
+
+  q = [3];
+  d = q - p; // expected-warning{{Subtraction of two pointers that}}
+
+  q = a + 10;
+  d = q - p; // no warning (use of pointer to one after the end is allowed)
+  d = [4] - a; // no warning
+
+  q = a + 11;
+  d = q - a; // ?
+
+  d =  - p; // expected-warning{{Subtraction of two pointers that}}
+}
+
+void f3(void) {
+  int a[3][4];
+  int d;
+
+  d = &(a[2]) - &(a[1]);
+  d = a[2] - a[1]; // expected-warning{{Subtraction of two pointers that}}
+  d = a[1] - a[1];
+  d = &(a[1][2]) - &(a[1][0]);
+  d = &(a[1][2]) - &(a[0][0]); // expected-warning{{Subtraction of two 
pointers that}}
+}
+
+void f4(void) {
+  int n = 4, m = 3;
+  int a[n][m];
+  int (*p)[m] = a; // p == [0]
+  p += 1; // p == [1]
+  int d = p - a; // d == 1 // expected-warning{{subtraction of pointers to 
type 'int[m]' of zero size has undefined behavior}}
+
+  d = &(a[2]) - &(a[1]); // expected-warning{{subtraction of pointers to type 
'int[m]' of zero size has undefined behavior}}
+  d = a[2] - a[1]; // expected-warning{{Subtraction of two pointers that}}

NagyDonat wrote:

Could you add a FIXME comment which states that these "type 'int[m]' of zero 
size" warnings are false positives emitted by checker X (and they should be 
eliminated eventually)?

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


[clang] [analyzer][NFC] Fix comparison to True/False (PR #94038)

2024-06-03 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat commented:

This change follows both the letter and the spirit of PEP8. (Note that `True` 
and `False` are not "singletons like `None`" because the type `bool` has two 
possible values -- but different rules still claim that the original code was 
bad and the new code is good.)  

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


[clang] [clang][analyzer][NFC] Improve docs of alpha.unix.BlockInCriticalSection (PR #93812)

2024-05-31 Thread Donát Nagy via cfe-commits

NagyDonat wrote:

> My intention was to ease the review as much as possible by cutting them into 
> atomic parts.

This is a good idea in general, but I feel that these two changes are so 
trivial, that they'd be very easy to review even together. Feel free to merge 
them both in whatever combination you would like. 

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


[clang] [clang][analyzer][NFC] Improve docs of alpha.unix.BlockInCriticalSection (PR #93812)

2024-05-30 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

What's the relationship between this PR and 
https://github.com/llvm/llvm-project/pull/93799 ?

Otherwise, the change LGTM, but you might want to either unify these two NFC 
changes into a single commit or ensure that they're independent.

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


[clang] [clang][analyzer] Improved PointerSubChecker (PR #93676)

2024-05-30 Thread Donát Nagy via cfe-commits


@@ -0,0 +1,74 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.PointerSub -verify %s
+
+void f1(void) {
+  int x, y, z[10];
+  int d =  -  // expected-warning{{Subtraction of two pointers that do 
not point into the same array is undefined behavior}}
+  d = z -  // expected-warning{{Subtraction of two pointers that do not 
point into the same array is undefined behavior}}
+  d =  -  // expected-warning{{Subtraction of two pointers that do not 
point into the same array is undefined behavior}}

NagyDonat wrote:

> Wrt. ` - 1`, that should be valid as well, given that the resulting pointer 
> is not dereferenced.

The standard explicitly disallows this, see [[expr.add] part 
4.2](http://eel.is/c++draft/expr.add#4.2) and 4.3 (in the most recent C++ draft 
standard, other versions may be different).

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


[clang] [clang][analyzer] Improved PointerSubChecker (PR #93676)

2024-05-30 Thread Donát Nagy via cfe-commits


@@ -44,24 +44,30 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator 
*B,
 
   const MemRegion *LR = LV.getAsRegion();
   const MemRegion *RR = RV.getAsRegion();
-
-  if (!(LR && RR))
-return;
-
-  const MemRegion *BaseLR = LR->getBaseRegion();
-  const MemRegion *BaseRR = RR->getBaseRegion();
-
-  if (BaseLR == BaseRR)
+  if (!LR || !RR)
 return;
 
-  // Allow arithmetic on different symbolic regions.
-  if (isa(BaseLR) || isa(BaseRR))
-return;
+  const auto *ElemLR = dyn_cast(LR);
+  const auto *ElemRR = dyn_cast(RR);
+  // FIXME: We want to verify that these are elements of an array.
+  // Because behavior of ElementRegion it may be confused with a cast.
+  // There is not a simple way to distinguish it from array element (check the
+  // types?). Because this missing check a warning is missing in the rare case
+  // when two casted pointers to the same region (variable) are subtracted.

NagyDonat wrote:

I discussed your examples and questions with @whisperity and Zoltán Porkoláb, 
and I'm trying to summarize what we determined. Note that I'm mostly working 
from the most recent C++ draft standard (http://eel.is/c++draft/), so some the 
conclusions may be invalid in C or older versions of C++ (but I tried to 
highlight the differences that I know about).

(1) In your first example the step `int *b = a` is invalid because the 
`int[3][3]` array `a` decays to an `int (*)[3]` (pointer to array of 3 `int`s) 
and that type is not interconvertible with a plain `int *` (see [ 
[basic.compound] note 5](http://eel.is/c++draft/basic.compound#note-5) in the 
C++ draft standard). (And if you define `b` as `int (*b)[3] = a`, then the 
pointer subtraction will become invalid.)

(2) In the second example using a `long *` to initialize `char *` or `short *` 
variables is _usually_ an error, it's accepted under old C, but in C++ you need 
an explicit cast and e.g. modern GCC also produces an error 
(`-Wincompatible-pointer-types` a warning that's by default an error) when it 
compiles this.

I'd guess that the actual pointer arithmetic _is_ standard-compliant, but the 
relevant parts of the standard ([[expr.reinterpret.cast] 
7](http://eel.is/c++draft/expr.post#expr.reinterpret.cast-7), 
[[expr.static.cast] 
14](http://eel.is/c++draft/expr.post#expr.static.cast-14))are too vague to give 
a confident answer.

Note that under C++ _accessing_ the element `short b[1]` would be a violation 
of [[basic.lval] part 
11](http://eel.is/c++draft/basic.lval#def:type-accessible), but based on 
[[defns.access]](http://eel.is/c++draft/defns.access) I'd say that the 
expression `[1]` is _not_ an access of `b[1]`.

(3) In your third example `[2][2] - [1][1]` is clearly working in 
practically all implementations, but we're fairly sure that it's not compliant 
with the C++ standard, because [ [expr.add] part 
5.2](https://www.eel.is/c++draft/expr.add#5.2) speaks about "array elements _i_ 
and _j_ of the same array object _x_" (and later "_i_ - _j_" which shows that 
"_i_" and "_j_" are scalar numbers) -- while in your example `a[2][2]` and 
`a[1][1]` are not (numerically indexed) elements within the same array. (This 
is coherent with [[dcl.array]](http://eel.is/c++draft/dcl.array) where an 
"array" implicitly means a one-dimensional array structure (whose elements may 
be other arrays).)

Nevertheless, it may be reasonable to avoid emitting warnings on this kind of 
code, because that could be better for the users.

(4) The definition of "_what exactly an "array object" is_" and "what is an 
_element_ of an array" primarily appears at [[dcl.array] part 
6](http://eel.is/c++draft/dcl.array#6):

> An object of type “array of N U” consists of a contiguously allocated 
> non-empty set of N subobjects of type U, known as the _elements_ of the 
> array, and numbered 0 to N-1.

(This clearly shows that the _element of an element of_ an array is not an 
_element of_ the array. The notion of "multi-dimensional arrays" only appears 
in the _Example_ [[dcl.array] Example 
4](http://eel.is/c++draft/dcl.array#example-4) with word choices that suggests 
that this is just a mathematical/intuitive notion and not something that's 
well-defined in the standard.)

This general definition is augmented by [[basic.compound] part 3, sentence 
11](http://eel.is/c++draft/basic.compound#3.sentence-11) which states that:

> For purposes of pointer arithmetic 
> ([[expr.add]](http://eel.is/c++draft/expr.add)) and comparison 
> ([[expr.rel]](http://eel.is/c++draft/expr.rel), 
> [[expr.eq]](http://eel.is/c++draft/expr.eq)), a pointer past the end of the 
> last element of an array x of n elements is considered to be equivalent to a 
> pointer to a hypothetical array element n of x and an object of type T that 
> is not an array element is considered to belong to an array with one element 
> of type T.

(5) Yes, the sub-arrays of a multidimensional array are separate "array 
objects" that have their own 

[clang] [clang][analyzer][NFC] Add test for a limitation of alpha.unix.Bloc… (PR #93799)

2024-05-30 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

It's good to document this, the commit LGTM. Are you planning to fix this soon?

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


  1   2   3   >