diff options
| author | Eli Friedman <efriedma@qti.qualcomm.com> | 2026-04-28 13:40:04 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-28 13:40:04 -0700 |
| commit | 898eabc27d1f112de0e1372147db8f0573d2a63f (patch) | |
| tree | 9c7f5a1332553d4f23ddfc017bc174827cf935cf | |
| parent | c147ccadae917314a7d46510936e5c275e14fc18 (diff) | |
| download | llvm-898eabc27d1f112de0e1372147db8f0573d2a63f.tar.gz llvm-898eabc27d1f112de0e1372147db8f0573d2a63f.tar.bz2 llvm-898eabc27d1f112de0e1372147db8f0573d2a63f.zip | |
[clang] Fix interaction of __ob_wrap with signed divide. (#194474)
At first glance, signed divide overflow seems similar to other forms of
signed overflow, but it's significantly different: it's the only form of
signed overflow that is not affected by -fwrapv, it has undefined
behavior at the LLVM IR level, and it can trigger trap on x86.
Given that, make ubsan trigger on signed divide overflow even if a type
is marked __ob_wrap.
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGen/overflow-behavior-types.c | 6 |
2 files changed, 5 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index c2188933ca2a..d60f1b37be50 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4230,7 +4230,7 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck( if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) && Ops.Ty->hasSignedIntegerRepresentation() && !IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) && - Ops.mayHaveIntegerOverflow() && !Ops.Ty.isWrapType() && + Ops.mayHaveIntegerOverflow() && !CGF.getContext().isTypeIgnoredBySanitizer( SanitizerKind::SignedIntegerOverflow, Ops.Ty)) { llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType()); diff --git a/clang/test/CodeGen/overflow-behavior-types.c b/clang/test/CodeGen/overflow-behavior-types.c index 109888f70750..7047d88035a9 100644 --- a/clang/test/CodeGen/overflow-behavior-types.c +++ b/clang/test/CodeGen/overflow-behavior-types.c @@ -62,11 +62,13 @@ void test1(int __ob_wrap a, int __ob_trap b) { // DEFAULT: llvm.sadd.with.overflow.i32 ++b; + // Despite the fact that "a" is marked as "wrapping", we still perform an + // overflow check: an overflowing divide has undefined behavior at the + // LLVM IR level (and will trap on x86). volatile extern int divisor; // DEFAULT: %[[T0:.*]] = load i32, ptr %a // DEFAULT-NEXT: %[[T1:.*]] = load volatile i32, ptr @divisor - // DEFAULT-NOT: br {{.*}} %handler.divrem_overflow - // DEFAULT: sdiv i32 %[[T0]], %[[T1]] + // DEFAULT: br {{.*}} %handler.divrem_overflow a/divisor; // DEFAULT: %[[T0:.*]] = load i32, ptr %b |
