[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-25 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt created 
https://github.com/llvm/llvm-project/pull/86618

## Intro

This attribute would allow for more granular control over what expressions can 
emit integer overflow warnings or integer overflow sanitizer errors.

 Here are some examples:

_copy-pasted from my 
[RFC.](https://discourse.llvm.org/t/rfc-add-wraps-attribute-for-granular-integer-overflow-handling/77670)_


When compiling with 
`-fsanitize=signed-integer-overflow,unsigned-integer-overflow`:

```c
typedef int __attribute__((wraps)) wrapping_int;

wrapping_int A = INT_MAX;
++A; /* This will not trigger a runtime sanitizer error */
```

```c
unsigned long addr __attribute__((wraps)); /* wraps can be added to variables */
unsigned long size; /* both operands don't need wraps, just one */
...
if (addr + size < addr) {
  // handle overflow gracefully, because the overflow sanitizer won't trip
}
...
```

```c
typedef int __attribute__((wraps)) wrapping_int;

int a = (wrapping_int) INT_MAX + 1; // no sanitizer trip (or -Winteger-overflow)
```

The next few examples will show some cases where sanitizers will still trip (by 
design):

```c
wrapping_int A = INT_MAX;
int B = 1;

A = INT_MAX + 1; // overflow sanitizer trips! (INT_MAX + 1) is computed and 
trips the sanitizer before assignment to A

B = (INT_MAX+B) * A; // overflow sanitizer trips!

B =  INT_MAX + B * A; // overflow sanitizer does NOT trip!
// This is because B * A is computed first, the result type carries the wraps 
attribute
// with it from A, then that result is used in summation with INT_MAX.
```

## Reasoning
The root cause of many security vulnerabilities in the Linux kernel is 
[arithmetic overflow](https://cwe.mitre.org/data/definitions/190.html). 

The currently available choices to control arithmetic overflow behavior are 
very limited. The instrumentation is "all or nothing" which lacks the 
granularity required for many cases.

Enabling or disabling a sanitizer like ``-fsanitize=unsigned-integer-overflow`` 
completely opts you in or out of instrumentation for __all__ unsigned 
arithmetic. For functions where intentional wrap-around is performed you could 
use ``__attribute__((no_sanitize("unsigned-integer-overflow")))`` to completely 
disable sanitizer instrumentation. This, however, is not ideal if your function 
is large and multi-purposed -- perhaps even containing loads of arithmetic that 
you don't want to disable instrumentation for. Getting more granular, we have 
compiler built-ins like ``__builtin_add_overflow()`` or similar. However, in 
some codebases, refactoring existing arithmetic to utilize these overflow 
builtins may only serve to complicate code. For example, the Linux Kernel has, 
like lots of other projects, some agreed upon idioms which are understood by 
its developers and changing these patterns is [frowned 
upon](https://lore.kernel.org/all/CAHk-=whs7fsbboo1gxe+83two2jegnsukmhacfwymw9auqb...@mail.gmail.com):


"if there's some unsigned wrap-around checker that doesn't
understand this traditional way of doing overflow checking, that piece
of crap needs fixing." - Linus 


This was in response to a patch that was trying to change the commonly accepted 
idiom: `base + offset < base` to utilize a builtin (via a macro) to silence 
sanitizer errors.

Recently, there's been some effort by Kees, myself and others to reintroduce 
the signed and unsigned integer overflow sanitizers in the Linux Kernel. Upon 
turning these sanitizers back on (or for the case of signed-integer-overflow, 
[making it work at all](https://github.com/llvm/llvm-project/pull/82432)) we 
encountered plently of existing instances of integer overflow in the Kernel. 
However, there's some pushback when trying to alter the "traditional" way of 
doing things.

With this new wrapping attribute we can specifically craft types that disable 
overflow instrumentation, without modifying traditional and widely understood 
code patterns -- resulting in easier to read code.

### To summarize the behavior:

Using ``__attribute__((wraps))`` on a typedef or variable declaration makes it 
a "wrapping" type or variable thereby disabling overflow instrumentation for 
either 1) arithmetic performed directly on wrapping variables or types or 2) 
arithmetic performed on the result of calculations containing a wrapping 
variable or type. Instrumentation is not disabled for calculations containing 
subexpressions wherein no wrapping variables are present.


## Other Notes

* ``[[wraps]]`` and ``[[clang::wraps]]`` are supported for C++11

* The wraps attribute cannot be applied to functions

* The wraps attribute _can_ be applied to member variables

* Constant expressions containing a wrapping type or variable should not result 
in `-Winteger-overflow` warnings either.

### CCs
@kees @nickdesaulniers @bwendling @erichkeane @haoNoQ @apple-fcloutier 
@FlashSheridan 




>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-25 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/2] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  7 ++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 296 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7fbe2fec6ca065..20bb9815830592 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -248,6 +248,13 @@ Attribute Changes in Clang
   added a new extension query ``__has_extension(swiftcc)`` corresponding to the
   ``__attribute__((swiftcc))`` attribute.
 
+- Introduced ``__attribute((wraps))`` or ``[[wraps]]`` which can be added to
+  type or variable declarations. Using an attributed type or variable in an
+  arithmetic expression will define the overflow behavior for that expression
+  as having two's complement wrap-around. These expressions cannot trigger
+  integer overflow warnings or sanitizer warnings. They also cannot be
+  optimized away by some eager UB optimizations.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..934146e8a182bc 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4084,6 +4084,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3e03e55612645b..0ea7755791d82e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4496,3 +4496,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 9de14f608fd114..af662702edcffa 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8005,3 +8005,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int offset)

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-26 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

cc: @MaskRay (since they also reviewed 
https://github.com/llvm/llvm-project/pull/82432)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-27 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> Adding attributes to types as type sugar (not part of the canonical type) is 
> generally problematic: non-canonical types are not reliably preserved 
> throughout the compiler, particularly in cases involving templates.

I see, here's an example that currently breaks my attribute (without any 
special handling):

```c++
typedef int __attribute__((wraps)) wrapping_int;

template 
void foo(T a) {
  ++a; // this will throw a sanitizer error because the generic method 
   // created for this templated type is generic
}

int main(void) {
  wrapping_int A = INT_MAX;
  foo(A);
}
```


> 
> Can we use a type qualifier here?

FWICT, qualifiers are extremely sparse with only a handful existing at all. 
```
Type.h +142:
/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
/// * MS: __unaligned
/// * Embedded C (TR18037): address spaces
/// * Objective C: the GC attributes (none, weak, or strong)
```

Most if not all type qualifiers are strongly associated with how the storage 
memory of a type is handled. For the behavior needed out of `wraps`, I was 
thinking this kind of thing is typically done via an attribute. Something like 
[noderef](https://clang.llvm.org/docs/AttributeReference.html#noderef) is 
similar. You apply it to types which then adjusts Clang's handling of variables 
of that type.

If it comes down to it, we can make this attribute only available for C under 
``__attribute__(())`` or I can try to add support for templates to be made 
aware of specific type attributes.

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-08 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

ping!



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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECKSIW
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO

JustinStitt wrote:

My patch does not touch SIO but in my testing I wanted it to be clear that SIO 
and SIW behave differently when `-fwrapv` is enabled. The tests more or less 
show this difference .

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 7774e4036ac1de7fdf5fe4c6b3208b492853ffc5 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/6] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f645..b987b26f93c39a 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index aa805f291d1757..5c05a0d7524244 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2516,6 +2521,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3409,7 +3420,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3417,7 +3428,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3430,8 +3442,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOve

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 7774e4036ac1de7fdf5fe4c6b3208b492853ffc5 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/8] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f645..b987b26f93c39a 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index aa805f291d1757..5c05a0d7524244 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2516,6 +2521,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3409,7 +3420,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3417,7 +3428,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3430,8 +3442,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOve

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits


@@ -3554,12 +3572,20 @@ Value 
*ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
   const std::string *handlerName =
 &CGF.getLangOpts().OverflowHandler;
   if (handlerName->empty()) {
-// If the signed-integer-overflow sanitizer is enabled, emit a call to its
-// runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
-if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
+// If the signed-integer-overflow or signed-integer-wrap sanitizer is
+// enabled, emit a call to its runtime. Otherwise, this is a -ftrapv check,
+// so just emit a trap.
+if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) ||
+CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {

JustinStitt wrote:

Yes, fixed in 
[e964431](https://github.com/llvm/llvm-project/pull/80089/commits/e96443184c6059ab8c5b97badc9ecc7270d4d466)

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECKSIW
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO

JustinStitt wrote:

I moved the tests in 
[5497e8b](https://github.com/llvm/llvm-project/pull/80089/commits/5497e8bc6849bf64c1158ff16b4aa04fd9141920);
 as such, I am no longer adding tests related to SIO.

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECKSIW
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO
+
+extern volatile int a, b, c;
+
+// CHECKSIW-LABEL: define void @test_add_overflow

JustinStitt wrote:

Resolved in 
[5497e8b](https://github.com/llvm/llvm-project/pull/80089/commits/5497e8bc6849bf64c1158ff16b4aa04fd9141920)
 since the tests have been moved there is no issue with LABEL statements or 
prefixes.

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv

JustinStitt wrote:

Gotcha, I did just that in 
[5497e8b](https://github.com/llvm/llvm-project/pull/80089/commits/5497e8bc6849bf64c1158ff16b4aa04fd9141920).
 Thanks Nick!

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 7774e4036ac1de7fdf5fe4c6b3208b492853ffc5 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/9] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f645..b987b26f93c39a 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index aa805f291d1757..5c05a0d7524244 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2516,6 +2521,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3409,7 +3420,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3417,7 +3428,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3430,8 +3442,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOve

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 7774e4036ac1de7fdf5fe4c6b3208b492853ffc5 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 01/10] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f645..b987b26f93c39a 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index aa805f291d1757..5c05a0d7524244 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2516,6 +2521,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3409,7 +3420,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3417,7 +3428,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3430,8 +3442,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotO

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-13 Thread Justin Stitt via cfe-commits

JustinStitt wrote:


> UBSan is documented clang/docs/UndefinedBehaviorSanitizer.rst 
> https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
> 
> Please make sure to update the list [of available 
> checks](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks).
> 
> Please also update the release notes to mention this feature. 
> clang/docs/ReleaseNotes.rst
>

Gotcha, done in 
[e15b6e6](https://github.com/llvm/llvm-project/pull/80089/commits/e15b6e636c27d00a4ef8d0a0f8f648bdcf11d44b)
 and 
[b978be6](https://github.com/llvm/llvm-project/pull/80089/commits/b978be62ca2d841d82924b702e8ab2b865754227).


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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-30 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt created 
https://github.com/llvm/llvm-project/pull/80089

**Reasoning**
Clang has a `signed-integer-overflow` sanitizer to catch arithmetic overflow; 
however, most* of its instrumentation [fails to 
apply](https://godbolt.org/z/ee41rE8o6) when `-fwrapv` is enabled.

The kernel enables `-fno-strict-overflow` which implies `-fwrapv`. This means 
we are [currently unable to detect signed-integer 
wrap-around](https://github.com/KSPP/linux/issues/26). All the while, the root 
cause of many security vulnerabilities in the Linux kernel is [arithmetic 
overflow](https://cwe.mitre.org/data/definitions/190.html)

In short, we need a way to instrument signed arithmetic even when the overflow 
behavior is *technically* defined due to `-fwrapv`. I propose we name the 
sanitizer "signed-integer-wrap" as it best captures the language semantics at 
hand.

*\* it seems division and modulo arithmetic is still instrumented with 
`-fsanitize=signed-integer-overflow` and `-fwrapv`*

**Other Notes**
* The `unsigned-integer-overflow` sanitizer is *probably* named incorrectly 
because "a computation involving unsigned operands can never overflow" 
[1](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf). 

* Perhaps this sanitizer does not belong in the **U**ndefined **B**ehavior 
Sanitizer as wrap-around is not UB (although the instrumentation is exactly the 
same).

* I tried running clang-format but the diff was huge and beyond just my 
changes. 

cc: @nickdesaulniers @kees @nathanchance @bwendling


>From 68805d7871230033be43c1d87dfcd2aa2b668589 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/3] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f64..b987b26f93c39 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 5502f685f6474..74e016fe4899f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2517,6 +2522,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CG

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 68805d7871230033be43c1d87dfcd2aa2b668589 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/4] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f64..b987b26f93c39 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 5502f685f6474..74e016fe4899f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2517,6 +2522,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3410,7 +3421,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3418,7 +3429,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3431,8 +3443,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOverflo

[compiler-rt] [clang] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 68805d7871230033be43c1d87dfcd2aa2b668589 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/5] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f64..b987b26f93c39 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 5502f685f6474..74e016fe4899f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2517,6 +2522,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3410,7 +3421,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3418,7 +3429,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3431,8 +3443,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOverflo

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,66 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECK
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO
+
+extern volatile int a, b, c;
+
+// CHECK-LABEL: define void @test_add_overflow
+void test_add_overflow(void) {
+  // CHECK: [[ADD0:%.*]] = load {{.*}} i32
+  // CHECK-NEXT: [[ADD1:%.*]] = load {{.*}} i32
+  // CHECK-NEXT: {{%.*}} = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 
[[ADD0]], i32 [[ADD1]])
+  // CHECK: call void @__ubsan_handle_add_overflow
+
+  // CHECKSIO-NOT: call void @__ubsan_handle_add_overflow
+  a = b + c;
+}
+
+// CHECK-LABEL: define void @test_inc_overflow
+void test_inc_overflow(void) {
+  // This decays and gets handled by __ubsan_handle_add_overflow...
+  // CHECK: [[INC0:%.*]] = load {{.*}} i32
+  // CHECK-NEXT: call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[INC0]], 
i32 1)
+  // CHECK: br {{.*}} %handler.add_overflow
+
+  // CHECKSIO-NOT: br {{.*}} %handler.add_overflow

JustinStitt wrote:

Makes sense. Fixed in 
[4848e38](https://github.com/llvm/llvm-project/pull/80089/commits/4848e38223c4191c2e7d45839c2ec34341597c6c).

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv

JustinStitt wrote:

I must be doing something wrong because it suggest I remove all my `Check: 
...`'s and replcae them with `Check: {{.*}}`

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECK

JustinStitt wrote:

> `CHECK` is the implicit default prefix if otherwise unspecified. Being 
> explicit here is not necessary and is discouraged (unlike the zen of python).

Gotcha, should I rename Check to something else or just drop the --check-prefix 
entirely?


Also, the non-instrumented vs instrumented version don't have too much in 
common. Should I still opt for this shared --check-prefixes approach? 

Here's what we're workin' with:


clang -cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - 
-fsanitize=signed-integer-wrap san.c



```

; ModuleID = 'san.c'
source_filename = "san.c"
target datalayout = 
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin"

@b = external global i32, align 4
@c = external global i32, align 4
@.src = private unnamed_addr constant [6 x i8] c"san.c\00", align 1
@0 = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x 
i8] c"'int'\00" }
@1 = private unnamed_addr global { { ptr, i32, i32 }, ptr } { { ptr, i32, i32 } 
{ ptr @.src, i32 4, i32 9 }, ptr @0 }
@a = external global i32, align 4

; Function Attrs: noinline nounwind optnone
define void @test_add_overflow() #0 {
entry:
  %0 = load volatile i32, ptr @b, align 4
  %1 = load volatile i32, ptr @c, align 4
  %2 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %0, i32 %1), 
!nosanitize !2
  %3 = extractvalue { i32, i1 } %2, 0, !nosanitize !2
  %4 = extractvalue { i32, i1 } %2, 1, !nosanitize !2
  %5 = xor i1 %4, true, !nosanitize !2
  br i1 %5, label %cont, label %handler.add_overflow, !prof !3, !nosanitize !2

handler.add_overflow: ; preds = %entry
  %6 = zext i32 %0 to i64, !nosanitize !2
  %7 = zext i32 %1 to i64, !nosanitize !2
  call void @__ubsan_handle_add_overflow_abort(ptr @1, i64 %6, i64 %7) #3, 
!nosanitize !2
  unreachable, !nosanitize !2

cont: ; preds = %entry
  store volatile i32 %3, ptr @a, align 4
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn 
memory(none)
declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1

; Function Attrs: noreturn nounwind uwtable
declare void @__ubsan_handle_add_overflow_abort(ptr, i64, i64) #2

attributes #0 = { noinline nounwind optnone "min-legal-vector-width"="0" 
"no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn 
memory(none) }
attributes #2 = { noreturn nounwind uwtable }
attributes #3 = { noreturn nounwind }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 19.0.0git 
(https://github.com/JustinStitt/llvm-project.git 
3766054a825a7dd4ae69feb73c767029f86f912e)"}
!2 = !{}
!3 = !{!"branch_weights", i32 1048575, i32 1}

```



clang -cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - 
-fsanitize=signed-integer-overflow san.c




```

; ModuleID = 'san.c'
source_filename = "san.c"
target datalayout = 
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin"

@b = external global i32, align 4
@c = external global i32, align 4
@a = external global i32, align 4

; Function Attrs: noinline nounwind optnone
define void @test_add_overflow() #0 {
entry:
  %0 = load volatile i32, ptr @b, align 4
  %1 = load volatile i32, ptr @c, align 4
  %add = add i32 %0, %1
  store volatile i32 %add, ptr @a, align 4
  ret void
}

attributes #0 = { noinline nounwind optnone "min-legal-vector-width"="0" 
"no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"target-features"="+cx8,+mmx,+sse,+sse2,+x87" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 19.0.0git 
(https://github.com/JustinStitt/llvm-project.git 
3766054a825a7dd4ae69feb73c767029f86f912e)"}

```




diff



```diff

8,10d7
< @.src = private unnamed_addr constant [6 x i8] c"san.c\00", align 1
< @0 = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 
x i8] c"'int'\00" }
< @1 = private unnamed_addr global { { ptr, i32, i32 }, ptr } { { ptr, i32, i32 
} { ptr @.src, i32 4, i32 9 }, ptr @0 }
18,31c15,16
<   %2 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %0, i32 %1), 
!nosanitize !2
<   %3 = extractvalue { i32, i1 } %2, 0, !nosanitize !2
<   %4 = extractvalue { i32, i1 } %2, 1, !nosanitize !2
<   %5 = xor i1 %4, true, !nosanitize !2
<   br i1 %5, label %cont, label %handler.add_overflow, !prof !3, !nosanitize !2
< 
< handler.add_overflow: ; preds = %entry
<   %6 = zext i32 %0 to i64, !

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Hey, does anyone know why the CI bot (buildkite) fails my builds for a trailing 
whitespace in a file I did not touch?

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


[compiler-rt] [clang] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 68805d7871230033be43c1d87dfcd2aa2b668589 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 1/6] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f64..b987b26f93c39 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 5502f685f6474..74e016fe4899f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2517,6 +2522,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3410,7 +3421,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3418,7 +3429,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3431,8 +3443,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotOverflo

[compiler-rt] [clang] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECK

JustinStitt wrote:

Gotcha. Fixed in 
[f790b65](https://github.com/llvm/llvm-project/pull/80089/commits/f790b6522166cc59d900400f9e7beee5d8a19750).
 Thanks Nick!

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECKSIW
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO
+
+extern volatile int a, b, c;
+
+// CHECKSIW-LABEL: define void @test_add_overflow

JustinStitt wrote:

I believe @tschuett was saying that to be confident we are instrumenting the 
arithmetic (and the correct operands therein) we should check the overflow bit 
usage in the branch instruction. The only way I could think of doing this was 
capturing the call to the overflow intrinsic which returns the value and the 
overflow bit. Is there a way to minimize my CHECKs? 

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv

JustinStitt wrote:

I believe @tschuett was saying that to be confident we are instrumenting the 
arithmetic (and the correct operands therein) we should check the overflow bit 
usage in the branch instruction. The only way I could think of doing this was 
capturing the call to the overflow intrinsic which returns the value and the 
overflow bit. Is there a way to minimize my CHECKs?

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,77 @@
+// Check that -fsanitize=signed-integer-wrap instruments with -fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-wrap | FileCheck %s --check-prefix=CHECKSIW
+
+// Check that -fsanitize=signed-integer-overflow doesn't instrument with 
-fwrapv
+// RUN: %clang_cc1 -fwrapv -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fsanitize=signed-integer-overflow | FileCheck %s --check-prefix=CHECKSIO
+
+extern volatile int a, b, c;
+
+// CHECKSIW-LABEL: define void @test_add_overflow

JustinStitt wrote:

I was thinking to be certain that no instrumentation exists we just need to 
check that no call to the handler exists. The idea being that it's easier to 
disprove something than to prove it.

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-01-31 Thread Justin Stitt via cfe-commits

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


[clang] [CodeGen] Respect pointer-overflow sanitizer for void pointers (PR #67772)

2023-09-29 Thread Justin Stitt via cfe-commits

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

LGTM!

FWIW, here's a test file that does not trip the sanitizer before this PR and 
_does_ trip after the PR:

```c
#include 

int main(int argc, char **argv) {
  void *p = NULL;
  printf("p: %p\n", p);
  p = p - argc;
  printf("p: %p\n", p);
  return 0;
}

```

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/80089

>From 7774e4036ac1de7fdf5fe4c6b3208b492853ffc5 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jan 2024 23:28:42 +
Subject: [PATCH 01/11] add signed-integer-wrap sanitizer

---
 clang/include/clang/Basic/Sanitizers.def |  5 +-
 clang/lib/CodeGen/CGExprScalar.cpp   | 62 +++-
 compiler-rt/lib/ubsan/ubsan_checks.inc   |  2 +
 3 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/Sanitizers.def 
b/clang/include/clang/Basic/Sanitizers.def
index c2137e3f61f645..b987b26f93c39a 100644
--- a/clang/include/clang/Basic/Sanitizers.def
+++ b/clang/include/clang/Basic/Sanitizers.def
@@ -104,6 +104,7 @@ SANITIZER("shift-base", ShiftBase)
 SANITIZER("shift-exponent", ShiftExponent)
 SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
 SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("signed-integer-wrap", SignedIntegerWrap)
 SANITIZER("unreachable", Unreachable)
 SANITIZER("vla-bound", VLABound)
 SANITIZER("vptr", Vptr)
@@ -144,7 +145,7 @@ SANITIZER_GROUP("undefined", Undefined,
 IntegerDivideByZero | NonnullAttribute | Null | ObjectSize 
|
 PointerOverflow | Return | ReturnsNonnullAttribute | Shift 
|
 SignedIntegerOverflow | Unreachable | VLABound | Function |
-Vptr)
+Vptr | SignedIntegerWrap)
 
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
 SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
@@ -179,7 +180,7 @@ SANITIZER_GROUP("implicit-conversion", ImplicitConversion,
 SANITIZER_GROUP("integer", Integer,
 ImplicitConversion | IntegerDivideByZero | Shift |
 SignedIntegerOverflow | UnsignedIntegerOverflow |
-UnsignedShiftBase)
+UnsignedShiftBase | SignedIntegerWrap)
 
 SANITIZER("local-bounds", LocalBounds)
 SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index aa805f291d1757..5c05a0d7524244 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,6 +723,11 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (CanElideOverflowCheck(CGF.getContext(), Ops))
+return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+  return EmitOverflowCheckedBinOp(Ops);
+}
 return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -2516,6 +2521,12 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerWrap)) {
+  if (!E->canOverflow())
+return Builder.CreateNSWAdd(InVal, Amount, Name);
+  return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
+  E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts(;
+}
 return Builder.CreateAdd(InVal, Amount, Name);
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -3409,7 +3420,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const 
CompoundAssignOperator *E,
 
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
-  SmallVector, 2> Checks;
+  SmallVector, 3> Checks;
 
   if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
 Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
@@ -3417,7 +3428,8 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
   }
 
   const auto *BO = cast(Ops.E);
-  if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
+  if (CGF.SanOpts.hasOneOf(SanitizerKind::SignedIntegerOverflow |
+  SanitizerKind::SignedIntegerWrap) &&
   Ops.Ty->hasSignedIntegerRepresentation() &&
   !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
   Ops.mayHaveIntegerOverflow()) {
@@ -3430,8 +3442,13 @@ void 
ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
 llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
 llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
 llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
-Checks.push_back(
-std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
+if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  Checks.push_back(
+  std::make_pair(NotO

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> I think this patch is good to go. Thanks for working on it!

Thanks for the review Nick! BTW, I forgot to update the `ReleaseNotes.rst`, 
I've done so now (hopefully not voiding your previous review)



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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

My original idea was to get the SIO sanitizer working with `-fwrapv`, the issue 
[here](https://github.com/KSPP/linux/issues/26) even suggests it as a viable 
option. However, after seeing literal checks like:

```cpp
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
```

... I think the best option is to instrument a wrap sanitizer (which this PR 
does). A wrap sanitizer best captures the language semantics at hand while 
maintaining existing functionality of the SIO sanitizer. I think Kees can speak 
first hand about how picky some folks are about the language being used for 
this arithmetic overflow/wraparound stuff (he linked some gcc threads above my 
comment but I've also seen some spicy LKML discussions about how OVERFLOW 
doesn't exist in the Linux Kernel and as such WRAPAROUND instrumentation is 
needed).

I think this PR bridges the gap between folks like Kees (who just want all this 
suspicious kernel arithmetic to go away) and folks like Linus (who is really 
particular about language).

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> I believe we can move forward by reusing 
> `-fsanitize=signed-integer-overflow`, which adds least complexity to Clang 
> and is very reasonable.

I see a few problems with changing `-fsanitize=signed-integer-overflow`:

1) Clang no longer matches GCC's SIO functionality

2) Existing codebases (albeit, very few) may be affected by what is essentially 
a breaking change. 

3) The C spec language semantics all hint at `signed-integer-overflow` being a 
misnomer for the properties of the arithmetic we are sanitizing when `-fwrapv` 
is enabled. (really, `unsigned-integer-overflow` is also poorly named as 
unsigned arithmetic can't overflow 
[6.2.5.9](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf))

Should a compiler not at least put some effort into properly representing the 
semantics at hand?

@MaskRay, there's been lots of good review on this PR with folks more or less 
liking the direction of it. I'd like to find some common ground on this so we 
can move it forward. If you really think changing the SIO sanitizer is the way 
to go I'll probably close this PR and open a new one as it represents a wholly 
different idea.


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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -193,7 +193,14 @@ Available checks are:
  signed division overflow (``INT_MIN/-1``), but not checks for
  lossy implicit conversions performed before the computation
  (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ handled by ``-fsanitize=implicit-conversion`` group of checks. Note that
+ ``-fwrapv`` implicitly disables instrumentation for much of the arithmetic
+ covered by ``-fsanitize=signed-integer-overflow``.
+  -  ``-fsanitize=signed-integer-wrap``: Signed Integer wraparound, where the
+ result of a signed integer computation wraps around. Behaves identically
+ to ``-fsanitize=signed-integer-overflow`` when ``-fwrapv`` is enabled.
+ Without ``-fwrapv`` or ``-fno-strict-overflow``, this sanitizer will only
+ instrument division operations.

JustinStitt wrote:

I was going off the spec, but I think I may have misinterpreted it:

`
An implementation that defines signed integer types as also being modulo need 
not detect integer overflow, in which case, only integer divide-by-zero need be 
detected.
`

>From [H.2.2 Integer 
>Types](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf)

I initially read this as meaning we need to instrument division no matter what 
(just in case it's divide by zero or similar case). I can add a check for the 
signed overflow behavior for the division steps.

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -193,7 +193,14 @@ Available checks are:
  signed division overflow (``INT_MIN/-1``), but not checks for
  lossy implicit conversions performed before the computation
  (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ handled by ``-fsanitize=implicit-conversion`` group of checks. Note that
+ ``-fwrapv`` implicitly disables instrumentation for much of the arithmetic
+ covered by ``-fsanitize=signed-integer-overflow``.
+  -  ``-fsanitize=signed-integer-wrap``: Signed Integer wraparound, where the
+ result of a signed integer computation wraps around. Behaves identically
+ to ``-fsanitize=signed-integer-overflow`` when ``-fwrapv`` is enabled.
+ Without ``-fwrapv`` or ``-fno-strict-overflow``, this sanitizer will only
+ instrument division operations.

JustinStitt wrote:

> Actually it's very inconsistent that the sanitizer is less strict without 
> `-fwrapv`, when for `signed-integer-overflow` we have an opposite.

Yes, this proposed "wrap" wrap sanitize is less strict when nothing is defined 
as wrapping (i.e: missing `-fwrapv`). Should this not be the case?


In the same way, `signed-integer-overflow` is more strict without `-fwrapv` as 
things are  overflowing and not wrapping. 

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -193,7 +193,14 @@ Available checks are:
  signed division overflow (``INT_MIN/-1``), but not checks for
  lossy implicit conversions performed before the computation
  (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ handled by ``-fsanitize=implicit-conversion`` group of checks. Note that
+ ``-fwrapv`` implicitly disables instrumentation for much of the arithmetic
+ covered by ``-fsanitize=signed-integer-overflow``.
+  -  ``-fsanitize=signed-integer-wrap``: Signed Integer wraparound, where the

JustinStitt wrote:

I agree that the current version is not so clear. I must admit, though, I am 
not 100% sure what changes you would like. Vitaly, do you think it should be 
worded like such:

```
Note that ``-fwrapv`` implicitly disables most checks performed by this 
sanitizer 
as the overflow behavior is well-defined.
```

If this doesn't match what you were thinking could you let me know?

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


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt created 
https://github.com/llvm/llvm-project/pull/82432

**Reasoning**
Clang has a `signed-integer-overflow` sanitizer to catch arithmetic overflow; 
however, most of its instrumentation [fails to 
apply](https://godbolt.org/z/ee41rE8o6) when `-fwrapv` is enabled; this is by 
design.

The Linux kernel enables `-fno-strict-overflow` which implies `-fwrapv`. This 
means we are [currently unable to detect signed-integer 
wrap-around](https://github.com/KSPP/linux/issues/26). All the while, the root 
cause of many security vulnerabilities in the Linux kernel is [arithmetic 
overflow](https://cwe.mitre.org/data/definitions/190.html). 

To work around this and enhance the functionality of 
`-fsanitize=signed-integer-overflow`, let's instrument signed arithmetic even 
if the signed overflow behavior is defined.

Initially, I created a [new sanitizer @ 
(pr/80089)](https://github.com/llvm/llvm-project/pull/80089) but simply 
changing the SIO sanitizer itself may be the better approach as per @MaskRay 's 
review from that PR.

cc: @nickdesaulniers @kees @nathanchance @bwendling @MaskRay 


>From b02b09b9eb4f9a8ac60dd077d95c67b959db3b70 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 20 Feb 2024 22:21:02 +
Subject: [PATCH] support fwrapv with signed int overflow sanitizer

---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/docs/UndefinedBehaviorSanitizer.rst |  9 +
 clang/lib/CodeGen/CGExprScalar.cpp| 16 
 clang/test/CodeGen/integer-overflow.c | 12 
 4 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..685b19cabeb82c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.
+
 Python Binding Changes
 --
 
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst 
b/clang/docs/UndefinedBehaviorSanitizer.rst
index b8ad3804f18903..8f58c92bd2a163 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -190,10 +190,11 @@ Available checks are:
   -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
  result of a signed integer computation cannot be represented in its type.
  This includes all the checks covered by ``-ftrapv``, as well as checks for
- signed division overflow (``INT_MIN/-1``), but not checks for
- lossy implicit conversions performed before the computation
- (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ signed division overflow (``INT_MIN/-1``). Note that checks are still
+ added even when ``-fwrapv`` is enabled. This sanitizer does not check for
+ lossy implicit conversions performed before the computation (see
+ ``-fsanitize=implicit-conversion``). Both of these two issues are handled
+ by ``-fsanitize=implicit-conversion`` group of checks.
   -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
  program point.
   -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 576734e460b9c1..7621d9bcdec991 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,7 +723,9 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -2568,7 +2570,9 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateAdd(InVal, Amount, Name);
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(InVal, Amount, Name);
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWAdd(InVal, Amount, Name);
@@ -3913,7 +3917,9 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
   if (op.Ty->isSignedIntegerOrEnumerationType()) {
 switch (CGF.getLangOpts().getSignedOverflowBehav

[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/82432

>From b02b09b9eb4f9a8ac60dd077d95c67b959db3b70 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 20 Feb 2024 22:21:02 +
Subject: [PATCH 1/2] support fwrapv with signed int overflow sanitizer

---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/docs/UndefinedBehaviorSanitizer.rst |  9 +
 clang/lib/CodeGen/CGExprScalar.cpp| 16 
 clang/test/CodeGen/integer-overflow.c | 12 
 4 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..685b19cabeb82c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.
+
 Python Binding Changes
 --
 
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst 
b/clang/docs/UndefinedBehaviorSanitizer.rst
index b8ad3804f18903..8f58c92bd2a163 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -190,10 +190,11 @@ Available checks are:
   -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
  result of a signed integer computation cannot be represented in its type.
  This includes all the checks covered by ``-ftrapv``, as well as checks for
- signed division overflow (``INT_MIN/-1``), but not checks for
- lossy implicit conversions performed before the computation
- (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ signed division overflow (``INT_MIN/-1``). Note that checks are still
+ added even when ``-fwrapv`` is enabled. This sanitizer does not check for
+ lossy implicit conversions performed before the computation (see
+ ``-fsanitize=implicit-conversion``). Both of these two issues are handled
+ by ``-fsanitize=implicit-conversion`` group of checks.
   -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
  program point.
   -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 576734e460b9c1..7621d9bcdec991 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,7 +723,9 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -2568,7 +2570,9 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateAdd(InVal, Amount, Name);
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(InVal, Amount, Name);
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWAdd(InVal, Amount, Name);
@@ -3913,7 +3917,9 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
   if (op.Ty->isSignedIntegerOrEnumerationType()) {
 switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
 case LangOptions::SOB_Defined:
-  return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  [[fallthrough]];
 case LangOptions::SOB_Undefined:
   if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
 return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
@@ -4067,7 +4073,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
 if (op.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateSub(op.LHS, op.RHS, "sub");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateSub(op.LHS, op.RHS, "sub");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
d

[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> ⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️
> 
> You can test this locally with the following command:
> View the diff from clang-format here.

Fixed in 
[e5e92e6](https://github.com/llvm/llvm-project/pull/82432/commits/e5e92e6c07a9fbbac698a3b6bb4422f26ea06583)

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -723,7 +723,9 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))

JustinStitt wrote:

One creates `CreateMul` and other `CreateNSWMul`. I believe this is useful for 
optimizations later

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.

JustinStitt wrote:

Doesn't `-fno-sanitizer-signed-integer-overflow` already work? I did some 
[testing in godbolt](https://godbolt.org/z/oWdxvzs4P) and I am able to toggle 
this sanitizer on/off.

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/82432

>From b02b09b9eb4f9a8ac60dd077d95c67b959db3b70 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 20 Feb 2024 22:21:02 +
Subject: [PATCH 1/3] support fwrapv with signed int overflow sanitizer

---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/docs/UndefinedBehaviorSanitizer.rst |  9 +
 clang/lib/CodeGen/CGExprScalar.cpp| 16 
 clang/test/CodeGen/integer-overflow.c | 12 
 4 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..685b19cabeb82c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.
+
 Python Binding Changes
 --
 
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst 
b/clang/docs/UndefinedBehaviorSanitizer.rst
index b8ad3804f18903..8f58c92bd2a163 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -190,10 +190,11 @@ Available checks are:
   -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
  result of a signed integer computation cannot be represented in its type.
  This includes all the checks covered by ``-ftrapv``, as well as checks for
- signed division overflow (``INT_MIN/-1``), but not checks for
- lossy implicit conversions performed before the computation
- (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ signed division overflow (``INT_MIN/-1``). Note that checks are still
+ added even when ``-fwrapv`` is enabled. This sanitizer does not check for
+ lossy implicit conversions performed before the computation (see
+ ``-fsanitize=implicit-conversion``). Both of these two issues are handled
+ by ``-fsanitize=implicit-conversion`` group of checks.
   -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
  program point.
   -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 576734e460b9c1..7621d9bcdec991 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,7 +723,9 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -2568,7 +2570,9 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateAdd(InVal, Amount, Name);
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(InVal, Amount, Name);
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWAdd(InVal, Amount, Name);
@@ -3913,7 +3917,9 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
   if (op.Ty->isSignedIntegerOrEnumerationType()) {
 switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
 case LangOptions::SOB_Defined:
-  return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  [[fallthrough]];
 case LangOptions::SOB_Undefined:
   if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
 return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
@@ -4067,7 +4073,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
 if (op.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateSub(op.LHS, op.RHS, "sub");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateSub(op.LHS, op.RHS, "sub");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
d

[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.

JustinStitt wrote:

Gotcha, resolved with 
[0182698](https://github.com/llvm/llvm-project/pull/82432/commits/018269881647673b530b8cb4611c7a380a5a1b5c).
 Let me know if this is detailed enough 😄 

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/82432

>From b02b09b9eb4f9a8ac60dd077d95c67b959db3b70 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 20 Feb 2024 22:21:02 +
Subject: [PATCH 1/4] support fwrapv with signed int overflow sanitizer

---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/docs/UndefinedBehaviorSanitizer.rst |  9 +
 clang/lib/CodeGen/CGExprScalar.cpp| 16 
 clang/test/CodeGen/integer-overflow.c | 12 
 4 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5bca2c965c866b..685b19cabeb82c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -399,6 +399,9 @@ Moved checkers
 Sanitizers
 --
 
+- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even
+  when ``-fwrapv`` is enabled. Previously, only division checks were enabled.
+
 Python Binding Changes
 --
 
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst 
b/clang/docs/UndefinedBehaviorSanitizer.rst
index b8ad3804f18903..8f58c92bd2a163 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -190,10 +190,11 @@ Available checks are:
   -  ``-fsanitize=signed-integer-overflow``: Signed integer overflow, where the
  result of a signed integer computation cannot be represented in its type.
  This includes all the checks covered by ``-ftrapv``, as well as checks for
- signed division overflow (``INT_MIN/-1``), but not checks for
- lossy implicit conversions performed before the computation
- (see ``-fsanitize=implicit-conversion``). Both of these two issues are
- handled by ``-fsanitize=implicit-conversion`` group of checks.
+ signed division overflow (``INT_MIN/-1``). Note that checks are still
+ added even when ``-fwrapv`` is enabled. This sanitizer does not check for
+ lossy implicit conversions performed before the computation (see
+ ``-fsanitize=implicit-conversion``). Both of these two issues are handled
+ by ``-fsanitize=implicit-conversion`` group of checks.
   -  ``-fsanitize=unreachable``: If control flow reaches an unreachable
  program point.
   -  ``-fsanitize=unsigned-integer-overflow``: Unsigned integer overflow, where
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 576734e460b9c1..7621d9bcdec991 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -723,7 +723,9 @@ class ScalarExprEmitter
 if (Ops.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -2568,7 +2570,9 @@ llvm::Value 
*ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
   StringRef Name = IsInc ? "inc" : "dec";
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateAdd(InVal, Amount, Name);
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(InVal, Amount, Name);
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWAdd(InVal, Amount, Name);
@@ -3913,7 +3917,9 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) {
   if (op.Ty->isSignedIntegerOrEnumerationType()) {
 switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
 case LangOptions::SOB_Defined:
-  return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+return Builder.CreateAdd(op.LHS, op.RHS, "add");
+  [[fallthrough]];
 case LangOptions::SOB_Undefined:
   if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
 return Builder.CreateNSWAdd(op.LHS, op.RHS, "add");
@@ -4067,7 +4073,9 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
 if (op.Ty->isSignedIntegerOrEnumerationType()) {
   switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
   case LangOptions::SOB_Defined:
-return Builder.CreateSub(op.LHS, op.RHS, "sub");
+if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
+  return Builder.CreateSub(op.LHS, op.RHS, "sub");
+[[fallthrough]];
   case LangOptions::SOB_Undefined:
 if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
   return Builder.CreateNSWSub(op.LHS, op.RHS, "sub");
d

[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits


@@ -70,6 +77,7 @@ void test1(void) {
   // WRAPV: add i8 {{.*}}, 1

JustinStitt wrote:

How's 
[1d9cb0a](https://github.com/llvm/llvm-project/pull/82432/commits/1d9cb0aca8985aa1636780b3ff9a863962cc2d57)
 look?

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


[clang] Sanitizer: Support -fwrapv with -fsanitize=signed-integer-overflow (PR #82432)

2024-02-20 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-09-04 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 06250aa308d1662848726528bd31395fb2ad3ea0 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 68 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 46 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 375 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1520f7a2916aae..e08240a8c1052e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -230,6 +230,16 @@ Attribute Changes in Clang
   instantiation by accidentally allowing it in C++ in some circumstances.
   (#GH106864)
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 65104acda93825..8702bb60b1db13 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4095,6 +4095,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext &Ctx) const;
+
 protected:
   BinaryOperator(const ASTContext &Ctx, Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 853226118af407..1bc488de5b2f71 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1454,6 +1454,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 8d2a362abc3c32..b6b4c8c2f35a7d 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4790,3 +4790,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index ef077db298831f..60379e836ad788 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8415,3 +8415,71 @@ of ``nonallocating`` by the compiler.
   }];
 }
 
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=

[clang] [Clang] Implement type filtering for overflow/truncation sanitizers w/ SSCLs (PR #107332)

2024-09-04 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt created 
https://github.com/llvm/llvm-project/pull/107332

[Related 
RFC](https://discourse.llvm.org/t/rfc-support-globpattern-add-operator-to-invert-matches/80683/5?u=justinstitt)

### Summary

Implement type-based filtering via [Sanitizer Special Case 
Lists](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html) for the 
arithmetic overflow and truncation sanitizers. 

Currently, using the `type:` prefix with these sanitizers does nothing. I've 
hooked up the SSCL parsing with Clang codegen so that we don't emit the 
overflow/truncation checks if the arithmetic contains an ignored type.

### Usefulness

You can craft ignorelists that ignore specific types that are expected to 
overflow or wrap-around. For example, to ignore `my_type` from 
`unsigned-integer-overflow` instrumentation:
```bash
$ cat ignorelist.txt
[unsigned-integer-overflow]
type:my_type

$ cat foo.c
typedef int my_type;
void foo() {
  my_type a = 2147483647;
  ++a;
}

$ clang foo.c -fsanitize=signed-integer-overflow 
-fsanitize-ignorelist=ignorelist.txt ; ./a.out
// --> no sanitizer error
```

If a type is functionally intended to overflow, like 
[refcount_t](https://kernsec.org/wiki/index.php/Kernel_Protections/refcount_t) 
and its associated APIs in the Linux kernel, then this type filtering would 
prove useful for reducing sanitizer noise. Currently, the Linux kernel dealt 
with this by 
[littering](https://elixir.bootlin.com/linux/v6.10.8/source/include/linux/refcount.h#L139
) `__attribute__((no_sanitize("signed-integer-overflow")))` annotations on all 
the `refcount_t` APIs. I think this serves as an example of how a codebase 
could be made cleaner. We could make custom types that are filtered out in an 
ignorelist, allowing for types to be more expressive -- without the need for 
annotations. This accomplishes a similar goal to 
https://github.com/llvm/llvm-project/pull/86618.


Yet another use case for this type filtering is whitelisting. We could ignore 
_all_ types, save a few.

```bash
$ cat ignorelist.txt
[implicit-signed-integer-truncation]
type:* # ignore literally all types
type:short=skip # except `short`

$ cat bar.c
// compile with -fsanitize=implicit-signed-integer-truncation
void bar(int toobig) {
  char a = toobig;  // not instrumented
  short b = toobig; // instrumented
}
```

### Other ways to accomplish the goal of sanitizer allowlisting/whitelisting
* ignore list SSCL type support (this PR that you're reading)
* [my sanitize-allowlist 
branch](https://github.com/llvm/llvm-project/compare/main...JustinStitt:llvm-project:sanitize-allowlist)
 - this just implements a sibling flag `-fsanitize-allowlist=`, removing some 
of the double negative logic present with `skip`/`ignore` when trying to 
whitelist something.
* [Glob 
Negation](https://discourse.llvm.org/t/rfc-support-globpattern-add-operator-to-invert-matches/80683)
 - Implement a negation operator to the GlobPattern class so the ignorelist 
query can use them to simulate allowlisting


Please let me know which of the three options we like best. They are not 
necessarily mutually exclusive.

Here's [another related PR](https://github.com/llvm/llvm-project/pull/86618) 
which implements a `wraps` attribute. This can accomplish a similar goal to 
this PR but requires in-source changes to codebases and also covers a wider 
variety of integer definedness problems.

### CCs
@kees @vitalybuka @bwendling 

>From 729329fc5769d913862281b8943471637ab30372 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 3 Sep 2024 18:28:53 -0700
Subject: [PATCH 1/3] hook up sscl categories with overflow/truncation
 sanitizers

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/ASTContext.h |  3 +
 clang/lib/AST/ASTContext.cpp | 31 +++
 clang/lib/CodeGen/CGExprScalar.cpp   | 36 +++-
 clang/test/CodeGen/ubsan-type-ignorelist.cpp | 88 +---
 4 files changed, 144 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 89bb5768dbd40d..a9373c6102c010 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -807,6 +807,9 @@ class ASTContext : public RefCountedBase {
 
   const NoSanitizeList &getNoSanitizeList() const { return *NoSanitizeL; }
 
+  bool isTypeIgnoredBySanitizer(const SanitizerMask &Mask,
+const QualType &Ty) const;
+
   const XRayFunctionFilter &getXRayFilter() const {
 return *XRayFilter;
   }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c61234aa4d1af1..bcda5fad585d67 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -817,6 +817,37 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
   return CanonTTP;
 }
 
+/// Check if a type can have its sanitizer instrumentation elided.
+/// Determine this by its presence in a SCL alongside its specified categories.
+/// For example

[clang] [Clang] Implement type filtering for overflow/truncation sanitizers w/ SSCLs (PR #107332)

2024-09-04 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 1/8] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf9..c329ee061cf00 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d86..4619e2d8c4fb7 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28..f253f7535776b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679..291739e1221d9 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee6..c07560c92100d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace {
+/// Certa

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -4248,6 +4248,22 @@ bool CompilerInvocation::ParseLangArgs(LangOptions 
&Opts, ArgList &Args,
   Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
   }
 
+  if (auto *A = Args.getLastArg(OPT_fsanitize_overflow_pattern_exclusion_EQ)) {
+for (int i = 0, n = A->getNumValues(); i != n; ++i) {
+  StringRef Value = A->getValue(i);
+  if (Value == "none")
+Opts.OverflowPatternExclusionMask |= LangOptionsBase::None;

JustinStitt wrote:

resolved with 4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,83 @@
+// Check for potential false positives from patterns that _almost_ match 
classic overflow-dependent or overflow-prone code patterns

JustinStitt wrote:

resolved in 4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -293,6 +293,40 @@ To silence reports from unsigned integer overflow, you can 
set
 ``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
 providing fuzzing signal without blowing up logs.
 
+Disabling instrumentation for common overflow patterns
+--
+
+There are certain overflow-dependent or overflow-prone code patterns which
+produce a lot of noise for integer overflow/truncation sanitizers. To disable
+instrumentation for these common patterns one should use
+``-fsanitize-overflow-pattern-exclusion=``.
+
+Currently, this option supports three pervasive overflow-dependent code idioms:

JustinStitt wrote:

thanks. resolved in 4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -555,6 +570,11 @@ class LangOptions : public LangOptionsBase {
   /// The default stream kind used for HIP kernel launching.
   GPUDefaultStreamKind GPUDefaultStream;
 
+  /// Which overflow patterns should be excluded from sanitizer instrumentation
+  int OverflowPatternExclusionMask = 0;

JustinStitt wrote:

gotcha, resolved with 4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -293,6 +293,40 @@ To silence reports from unsigned integer overflow, you can 
set
 ``-fsanitize-recover=unsigned-integer-overflow``, is particularly useful for
 providing fuzzing signal without blowing up logs.
 
+Disabling instrumentation for common overflow patterns
+--
+
+There are certain overflow-dependent or overflow-prone code patterns which
+produce a lot of noise for integer overflow/truncation sanitizers. To disable
+instrumentation for these common patterns one should use
+``-fsanitize-overflow-pattern-exclusion=``.
+
+Currently, this option supports three pervasive overflow-dependent code idioms:
+
+.. code-block:: c++
+
+/// -fsanitize-overflow-pattern-exclusion=negated-unsigned-const
+unsigned long foo = -1UL; // No longer causes a negation overflow warning
+unsigned long bar = -2UL; // and so on...
+
+.. code-block:: c++
+
+/// -fsanitize-overflow-pattern-exclusion=post-decr-while
+unsigned char count = 16;
+while (count--) { /* ... */ } // No longer causes 
unsigned-integer-overflow sanitizer to trip
+
+.. code-block:: c++
+
+/// -fsanitize-overflow-pattern-exclusion=add-overflow-test
+if (base + offset < base) { /* ... */ } // The pattern of `a + b < a`, and 
other re-orderings,
+// won't be instrumented (same for 
signed types)
+
+Negated unsigned constants, post-decrements in a while loop condition and

JustinStitt wrote:

right, that reads better. thanks!

resolved with 4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits


@@ -2877,6 +2888,17 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const 
UnaryOperator *E, LValue LV,
   } else if (type->isIntegerType()) {
 QualType promotedType;
 bool canPerformLossyDemotionCheck = false;
+
+// Is the pattern "while (i--)" and overflow exclusion?
+bool disableSanitizer =

JustinStitt wrote:

You're right. I split up the logic into a new method in 
4b3efbb41ff86eeff15671b1d876e1ef6a58a536

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-08 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

@bwendling I tried to address all your feedback points with 
4b3efbb41ff86eeff15671b1d876e1ef6a58a536 Let me know how that looks 👍 

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-12 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 1/9] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf90..c329ee061cf008 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..4619e2d8c4fb7f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..f253f7535776b8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679f..291739e1221d96 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee62..c07560c92100d7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace {

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-12 Thread Justin Stitt via cfe-commits


@@ -4759,6 +4759,55 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace {

JustinStitt wrote:

resolved by 
https://github.com/llvm/llvm-project/pull/100272/commits/2e3d4795633bb1a134be10b44e83a025a7b21d8e

thanks

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-12 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 01/10] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf90..c329ee061cf008 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..4619e2d8c4fb7f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..f253f7535776b8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679f..291739e1221d96 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee62..c07560c92100d7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace 

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-12 Thread Justin Stitt via cfe-commits


@@ -195,13 +196,23 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, 
const BinOpInfo &Op) {
   if (!Op.mayHaveIntegerOverflow())
 return true;
 
+  const UnaryOperator *UO = dyn_cast(Op.E);
+
+  if (UO && UO->getOpcode() == UO_Minus && UO->isIntegerConstantExpr(Ctx) &&
+  Ctx.getLangOpts().isOverflowPatternExcluded(
+  LangOptions::OverflowPatternExclusionKind::NegUnsignedConst))

JustinStitt wrote:

Nice catch, resolved in 
https://github.com/llvm/llvm-project/pull/100272/commits/cb0fcd1c3b1ded7258bb20cff4d187ca56f17149

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-12 Thread Justin Stitt via cfe-commits


@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool ExcludedOverflowPattern = false;

JustinStitt wrote:

Ok, I think I found a spare bit in `BinaryOperatorBits` but I am not super 
familiar with how all these bit classes work.

See: 
https://github.com/llvm/llvm-project/pull/100272/commits/cb0fcd1c3b1ded7258bb20cff4d187ca56f17149
 

Thanks

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 01/11] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf90..c329ee061cf008 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..4619e2d8c4fb7f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..f253f7535776b8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679f..291739e1221d96 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee62..c07560c92100d7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace 

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-13 Thread Justin Stitt via cfe-commits


@@ -649,6 +649,8 @@ class alignas(void *) Stmt {
 /// It is 0 otherwise.
 LLVM_PREFERRED_TYPE(bool)
 unsigned HasFPFeatures : 1;
+LLVM_PREFERRED_TYPE(bool)

JustinStitt wrote:

Good idea, see 
https://github.com/llvm/llvm-project/pull/100272/commits/e8afeed6dfc5d427b83d52d69c8f92b27fd1220e

thanks

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> I think serialization is missing for the new bit on BinaryOperator. 

How do I add this?



> I'm not sure why we're storing it in the first place, though; it's queried in 
> exactly one place, so there isn't really any benefit to precomputing it.

It's queried when we check if we can elide the overflow sanitizer check, at 
this point we're dealing with the BO responsible for the addition (or 
subtraction) and not with the BO responsible for comparison. To properly check 
for the entire pattern I am trying to exclude I am pretty sure I need that 
comparison BO; so I can either precompute comparison BOs and store a bit on its 
child BO or I navigate up the parent map from the child during the overflow 
ellision check.

Which is the better approach?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-08-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

A good example of a Linux kernel contributor running into an overflow that 
should really have its type marked as wrapping : 
https://lore.kernel.org/all/zrzk8hiladaj+...@gmail.com/

They could use this feature to mark the suspected field 
`percpu_ref->percpu_ref_data->count` as wrapping:

```c
struct percpu_ref_data {
atomic_long_t   count __attribute__((wraps));
...
};

// or mark the type `atomic_long_t` as wrapping
typedef atomic_t __attribute__((wraps)) atomic_long_t;
```

Reviewers, can I get a sense of where we are at with this feature? It lets 
developers better express the behavior of arithmetic in their code.

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-14 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 01/12] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf90..c329ee061cf008 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..4619e2d8c4fb7f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..f253f7535776b8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679f..291739e1221d96 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee62..c07560c92100d7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace 

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-14 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/100272

>From 154d3505ab13275086b3dffed67bcdcac52f79a3 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 23 Jul 2024 20:21:49 +
Subject: [PATCH 01/13] implement idiom exclusions

Add flag `-fno-sanitize-overflow-idioms` which disables integer
overflow/truncation sanitizer instrumentation for common
overflow-dependent code patterns.

Signed-off-by: Justin Stitt 
---
 clang/include/clang/AST/Expr.h|   5 +
 clang/include/clang/Basic/LangOptions.def |   2 +
 clang/include/clang/Driver/Options.td |  10 ++
 clang/include/clang/Driver/SanitizerArgs.h|   1 +
 clang/lib/AST/Expr.cpp|  53 +++
 clang/lib/CodeGen/CGExprScalar.cpp|  26 +++-
 clang/lib/Driver/SanitizerArgs.cpp|   7 +
 clang/lib/Driver/ToolChains/Clang.cpp |   7 +
 .../CodeGen/overflow-idiom-exclusion-fp.c |  77 ++
 clang/test/CodeGen/overflow-idiom-exclusion.c | 141 ++
 10 files changed, 327 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion-fp.c
 create mode 100644 clang/test/CodeGen/overflow-idiom-exclusion.c

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 5b813bfc2faf90..c329ee061cf008 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3860,6 +3860,7 @@ class CStyleCastExpr final
 class BinaryOperator : public Expr {
   enum { LHS, RHS, END_EXPR };
   Stmt *SubExprs[END_EXPR];
+  bool isOverflowIdiom;
 
 public:
   typedef BinaryOperatorKind Opcode;
@@ -4018,6 +4019,10 @@ class BinaryOperator : public Expr {
 return isShiftAssignOp(getOpcode());
   }
 
+  bool ignoreOverflowSanitizers() const {
+return isOverflowIdiom;
+  }
+
   /// Return true if a binary operator using the specified opcode and operands
   /// would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized
   /// integer to a pointer.
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..4619e2d8c4fb7f 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -400,6 +400,8 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
  "stop trivial automatic variable initialization if var size 
exceeds the specified size (in bytes). Must be greater than 0.")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, 
SOB_Undefined,
  "signed integer overflow handling")
+LANGOPT(IgnoreNegationOverflow, 1, 0, "ignore overflow caused by negation")
+LANGOPT(SanitizeOverflowIdioms, 1, 1, "enable instrumentation for common 
overflow idioms")
 ENUM_LANGOPT(ThreadModel  , ThreadModelKind, 2, ThreadModelKind::POSIX, 
"Thread Model")
 
 BENIGN_LANGOPT(ArrowDepth, 32, 256,
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index c8c56dbb51b28a..f253f7535776b8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2558,6 +2558,16 @@ defm sanitize_stats : BoolOption<"f", "sanitize-stats",
   "Disable">,
   BothFlags<[], [ClangOption], " sanitizer statistics gathering.">>,
   Group;
+defm sanitize_overflow_idioms : BoolFOption<"sanitize-overflow-idioms",
+  LangOpts<"SanitizeOverflowIdioms">, DefaultTrue,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " the instrumentation of common overflow 
idioms">>;
+defm sanitize_negation_overflow : BoolFOption<"sanitize-negation-overflow",
+  LangOpts<"IgnoreNegationOverflow">, DefaultFalse,
+  PosFlag,
+  NegFlag,
+  BothFlags<[], [ClangOption], " integer overflow sanitizer instrumentation 
for negation">>;
 def fsanitize_thread_memory_access : Flag<["-"], 
"fsanitize-thread-memory-access">,
  Group,
  HelpText<"Enable memory access 
instrumentation in ThreadSanitizer (default)">;
diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 47ef175302679f..291739e1221d96 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -64,6 +64,7 @@ class SanitizerArgs {
   // True if cross-dso CFI support if provided by the system (i.e. Android).
   bool ImplicitCfiRuntime = false;
   bool NeedsMemProfRt = false;
+  bool SanitizeOverflowIdioms = true;
   bool HwasanUseAliases = false;
   llvm::AsanDetectStackUseAfterReturnMode AsanUseAfterReturn =
   llvm::AsanDetectStackUseAfterReturnMode::Invalid;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9d5b8167d0ee62..c07560c92100d7 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4759,6 +4759,54 @@ ParenListExpr *ParenListExpr::CreateEmpty(const 
ASTContext &Ctx,
   return new (Mem) ParenListExpr(EmptyShell(), NumExprs);
 }
 
+namespace 

[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

@bwendling we want to use `-triple` not `-target`, can you cherry pick 
3ef83ad323dfbe99028c774c3716706671ba7b8b

I also reordered the tests and added labels so the tests are actually checking 
the right stuff -- debugging was really difficult but will be easier now.

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


[clang] [Clang] Overflow Pattern Exclusions (PR #100272)

2024-08-15 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> Sorry, but I am not sure why this didn't show up my 
> https://github.com/llvm/llvm-project/pulls?q=is%3Aopen+is%3Apr+review-requested%3A%40me+sort%3Aupdated-desc
>  I wanted to review this patch.

Did I do something wrong with my PR or fork settings? I am not sure why you 
weren't notified I left you on the CC and reviewer list. Thanks for your 
comments -- working on fixing the test cases right now.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/4] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  7 ++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 296 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7fbe2fec6ca065..20bb9815830592 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -248,6 +248,13 @@ Attribute Changes in Clang
   added a new extension query ``__has_extension(swiftcc)`` corresponding to the
   ``__attribute__((swiftcc))`` attribute.
 
+- Introduced ``__attribute((wraps))`` or ``[[wraps]]`` which can be added to
+  type or variable declarations. Using an attributed type or variable in an
+  arithmetic expression will define the overflow behavior for that expression
+  as having two's complement wrap-around. These expressions cannot trigger
+  integer overflow warnings or sanitizer warnings. They also cannot be
+  optimized away by some eager UB optimizations.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..934146e8a182bc 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4084,6 +4084,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3e03e55612645b..0ea7755791d82e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4496,3 +4496,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 9de14f608fd114..af662702edcffa 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8005,3 +8005,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int offset)

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/3] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int off

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Hi, I've made some changes and am looking for some more review on this PR:

* This attribute no longer supports C++ as there are other solutions for that 
language [1] that allow for the same fine-grained wrapping control without 
changing syntax patterns.
* Add bypass for implicit-(un)signed-integer-truncation sanitizers
* Rebased onto eec41d2f8d81b546d7b97648cca6b2d656104bd3

[1]: https://godbolt.org/z/7qPve6cWq (simple example)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/4] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int off

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/7] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int off

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;

JustinStitt wrote:

Hi, fixed with 5e6d926532c2cff3288f25e9b8f872e7f2ec9b65

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];

JustinStitt wrote:

Right, I had that originally. I shouldn't have changed it :)

Anyways, fixed in 0d7566777f06b3f2058d93dd77624ab2c66f1127

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}

JustinStitt wrote:

0d7566777f06b3f2058d93dd77624ab2c66f1127

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -2237,6 +2237,21 @@ bool 
BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx,
   return true;
 }
 
+bool BinaryOperator::oneOfWraps(const ASTContext &Ctx) const {
+  llvm::SmallVector Both = {getLHS(), getRHS()};

JustinStitt wrote:

I had trouble with your code snippet because `children()` gives `Stmt` 
iterators and I would have to add in a cast or two. I went with a simpler 
approach in a2f63982920f22d795c4971800bcc5cb55356570 (with 
QualType::hasWrapsAttr())

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -147,6 +147,15 @@ struct BinOpInfo {
   return UnOp->getSubExpr()->getType()->isFixedPointType();
 return false;
   }
+
+  /// Does the BinaryOperator have the wraps attribute?
+  /// If so, we can ellide overflow sanitizer checks.
+  bool oneOfWraps() const {
+const Type *TyPtr = E->getType().getTypePtrOrNull();
+if (TyPtr)

JustinStitt wrote:

Gotcha, checkout a2f63982920f22d795c4971800bcc5cb55356570

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -6954,6 +6954,23 @@ static void HandleBTFTypeTagAttribute(QualType &Type, 
const ParsedAttr &Attr,
   ::new (Ctx) BTFTypeTagAttr(Ctx, Attr, BTFTypeTag), Type);
 }
 
+static void handleWrapsAttr(QualType &Type, const ParsedAttr &Attr,
+TypeProcessingState &State) {
+  Sema &S = State.getSema();
+  ASTContext &Ctx = S.Context;
+
+  // No need to warn here, that is handled by SemaDeclAttr.
+  // Simply disable applying this attribute.
+  if (S.getLangOpts().CPlusPlus)

JustinStitt wrote:

Right! I missed this. Fixed!

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/8] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int off

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

The most recent commits have massively simplified checking for the wrapping 
attributes.

FWIW, the tests I am running are:
✅ `$ llvm-lit clang/test/CodeGen/integer-overflow.c -v`
✅ `$ llvm-lit clang/test/CodeGen/unsigned-overflow.c -v`
✅ `$ llvm-lit clang/test/Sema/attr-wraps.c -v`
...and some hand-rolled stuff I have.


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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/9] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext &Ctx) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int off

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> > Forbidding usage in C++ probably avoids the worst of the canonical-type 
> > issues, but there's still some potential for weird results. Particularly 
> > with type merging; for example, if you write `a ? (wrap_int)x : 1`, is the 
> > result a wrapping type?
> 
> I had a similar question in the general case: is the annotation contagious?
> 
> ```
> int foo(wrap_int x, int a, int b, int c) {
>   if (x + a + b < c)
> return 0;
>   return 1;
> }
> ```
> 
> The `x + a` is checked, but is that result checked when added to `b`?

Yes, it's "contagious":

```
|-FunctionDecl 0x55f64065a5d8  line:6:5 foo 'int 
(wrap_int, int, int, int)'
| |-ParmVarDecl 0x55f64065a300  col:18 used x 'wrap_int':'int'
| |-ParmVarDecl 0x55f64065a380  col:25 used a 'int'
| |-ParmVarDecl 0x55f64065a400  col:32 used b 'int'
| |-ParmVarDecl 0x55f64065a480  col:39 used c 'int'
| `-CompoundStmt 0x55f64065a8a8 
|   |-IfStmt 0x55f64065a858 
|   | |-BinaryOperator 0x55f64065a808  'int 
__attribute__((wraps))':'int' '<'
|   | | |-BinaryOperator 0x55f64065a7b0  'int 
__attribute__((wraps))':'int' '+'
|   | | | |-BinaryOperator 0x55f64065a758  'int 
__attribute__((wraps))':'int' '+'
|   | | | | |-ImplicitCastExpr 0x55f64065a728  'wrap_int':'int' 

|   | | | | | `-DeclRefExpr 0x55f64065a6e8  'wrap_int':'int' lvalue 
ParmVar 0x55f64065a300 'x' 'wrap_int':'int'
|   | | | | `-ImplicitCastExpr 0x55f64065a740  'int' 
|   | | | |   `-DeclRefExpr 0x55f64065a708  'int' lvalue ParmVar 
0x55f64065a380 'a' 'int'
|   | | | `-ImplicitCastExpr 0x55f64065a798  'int' 
|   | | |   `-DeclRefExpr 0x55f64065a778  'int' lvalue ParmVar 
0x55f64065a400 'b' 'int'
|   | | `-ImplicitCastExpr 0x55f64065a7f0  'int' 
|   | |   `-DeclRefExpr 0x55f64065a7d0  'int' lvalue ParmVar 
0x55f64065a480 'c' 'int'
|   | `-ReturnStmt 0x55f64065a848 
|   |   `-IntegerLiteral 0x55f64065a828  'int' 0
|   `-ReturnStmt 0x55f64065a898 
| `-IntegerLiteral 0x55f64065a878  'int' 1
```

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


  1   2   3   >