-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[UBSan] Diagnose assumption violation #104741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Yingwei Zheng (dtcxzyw) ChangesThis patch extends D34590 to check assumption violations. Full diff: https://github.com/llvm/llvm-project/pull/104741.diff 7 Files Affected:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f424ddaa175400..83da5d7d75be3b 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1996,16 +1996,21 @@ struct CallObjCArcUse final : EHScopeStack::Cleanup {
Value *CodeGenFunction::EmitCheckedArgForBuiltin(const Expr *E,
BuiltinCheckKind Kind) {
- assert((Kind == BCK_CLZPassedZero || Kind == BCK_CTZPassedZero)
- && "Unsupported builtin check kind");
+ assert((Kind == BCK_CLZPassedZero || Kind == BCK_CTZPassedZero ||
+ Kind == BCK_AssumePassedFalse) &&
+ "Unsupported builtin check kind");
- Value *ArgValue = EmitScalarExpr(E);
+ Value *ArgValue =
+ Kind == BCK_AssumePassedFalse ? EvaluateExprAsBool(E) : EmitScalarExpr(E);
if (!SanOpts.has(SanitizerKind::Builtin))
return ArgValue;
SanitizerScope SanScope(this);
- Value *Cond = Builder.CreateICmpNE(
- ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
+ Value *Cond =
+ Kind == BCK_AssumePassedFalse
+ ? ArgValue
+ : Builder.CreateICmpNE(
+ ArgValue, llvm::Constant::getNullValue(ArgValue->getType()));
EmitCheck(std::make_pair(Cond, SanitizerKind::Builtin),
SanitizerHandler::InvalidBuiltin,
{EmitCheckSourceLocation(E->getExprLoc()),
@@ -3424,7 +3429,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
if (E->getArg(0)->HasSideEffects(getContext()))
return RValue::get(nullptr);
- Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ Value *ArgValue =
+ EmitCheckedArgForBuiltin(E->getArg(0), BCK_AssumePassedFalse);
Function *FnAssume = CGM.getIntrinsic(Intrinsic::assume);
Builder.CreateCall(FnAssume, ArgValue);
return RValue::get(nullptr);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 7158a06e6bc3b3..291639346d8952 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -754,7 +754,8 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
const Expr *Assumption = cast<CXXAssumeAttr>(A)->getAssumption();
if (getLangOpts().CXXAssumptions &&
!Assumption->HasSideEffects(getContext())) {
- llvm::Value *AssumptionVal = EvaluateExprAsBool(Assumption);
+ llvm::Value *AssumptionVal =
+ EmitCheckedArgForBuiltin(Assumption, BCK_AssumePassedFalse);
Builder.CreateAssumption(AssumptionVal);
}
} break;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 57e0b7f91e9bf8..99db330f3316e5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5070,6 +5070,7 @@ class CodeGenFunction : public CodeGenTypeCache {
enum BuiltinCheckKind {
BCK_CTZPassedZero,
BCK_CLZPassedZero,
+ BCK_AssumePassedFalse,
};
/// Emits an argument for a call to a builtin. If the builtin sanitizer is
diff --git a/clang/test/CodeGen/ubsan-builtin-checks.c b/clang/test/CodeGen/ubsan-builtin-checks.c
index c7f6078f903bad..8535ec915ac346 100644
--- a/clang/test/CodeGen/ubsan-builtin-checks.c
+++ b/clang/test/CodeGen/ubsan-builtin-checks.c
@@ -51,3 +51,20 @@ void check_clz(int n) {
// CHECK: call void @__ubsan_handle_invalid_builtin
__builtin_clzg((unsigned int)n);
}
+
+// CHECK: define{{.*}} void @check_assume
+void check_assume(int n) {
+ // CHECK: [[TOBOOL:%.*]] = icmp ne i32 [[N:%.*]], 0
+ // CHECK-NEXT: br i1 [[TOBOOL]]
+ //
+ // Handler block:
+ // CHECK: call void @__ubsan_handle_invalid_builtin
+ // CHECK-NEXT: unreachable
+ //
+ // Continuation block:
+ // CHECK: call void @llvm.assume(i1 [[TOBOOL]])
+ __builtin_assume(n);
+
+ // CHECK: call void @__ubsan_handle_invalid_builtin
+ __attribute__((assume(n)));
+}
diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.cpp b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
index 27d01653f088da..44aec6b8b05cd2 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_handlers.cpp
@@ -633,9 +633,11 @@ static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
ScopedReport R(Opts, Loc, ET);
- Diag(Loc, DL_Error, ET,
- "passing zero to %0, which is not a valid argument")
- << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
+ if (Data->Kind == BCK_AssumePassedFalse)
+ Diag(Loc, DL_Error, ET, "assumption is violated during execution");
+ else
+ Diag(Loc, DL_Error, ET, "passing zero to %0, which is not a valid argument")
+ << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
}
void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.h b/compiler-rt/lib/ubsan/ubsan_handlers.h
index bae661a56833dd..4ffa1439a1323f 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers.h
+++ b/compiler-rt/lib/ubsan/ubsan_handlers.h
@@ -159,6 +159,7 @@ RECOVERABLE(implicit_conversion, ImplicitConversionData *Data, ValueHandle Src,
enum BuiltinCheckKind : unsigned char {
BCK_CTZPassedZero,
BCK_CLZPassedZero,
+ BCK_AssumePassedFalse,
};
struct InvalidBuiltinData {
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/builtins.cpp b/compiler-rt/test/ubsan/TestCases/Misc/builtins.cpp
index f8f564cb7baae2..3ebc8094298a0a 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/builtins.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/builtins.cpp
@@ -1,8 +1,8 @@
// REQUIRES: target={{x86_64.*}}
//
-// RUN: %clangxx -fsanitize=builtin -w %s -O3 -o %t
+// RUN: %clangxx -fsanitize=builtin -fno-inline -w %s -O3 -o %t
// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER
-// RUN: %clangxx -fsanitize=builtin -fno-sanitize-recover=builtin -w %s -O3 -o %t.abort
+// RUN: %clangxx -fsanitize=builtin -fno-inline -fno-sanitize-recover=builtin -w %s -O3 -o %t.abort
// RUN: not %run %t.abort 2>&1 | FileCheck %s --check-prefix=ABORT
void check_ctz(int n) {
@@ -28,8 +28,20 @@ void check_clz(int n) {
__builtin_clzll(n);
}
+void check_assume(int n) {
+ // RECOVER: builtins.cpp:[[@LINE+1]]:20: runtime error: assumption is violated during execution
+ __builtin_assume(n);
+}
+
+void check_assume_attr(int n) {
+ // RECOVER: builtins.cpp:[[@LINE+1]]:25: runtime error: assumption is violated during execution
+ __attribute__((assume(n)));
+}
+
int main() {
check_ctz(0);
check_clz(0);
+ check_assume(0);
+ check_assume_attr(0);
return 0;
}
|
Ping. |
1 similar comment
Ping. |
LGTM, but would like @vitalybuka to also take a quick look. |
Thanks! |
I'm concerned about the amount of code that might break. We have internally If it breaks to much, we will need to create a new sanitizers, e.g |
clang with UBSAN is fine, i am running other tests. |
…109088) This patch improves error message, and fixes a copy-paste mistake in GET_REPORT_OPTIONS argument. Address comment #104741 (comment). --------- Co-authored-by: Vitaly Buka <[email protected]>
Other tests are also fine. |
0a1584d
to
7bcaa3b
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
This has triggered a failure in our private builder (aarch64-ubuntu20.04)
|
I think it is not related to this patch. It only works with |
This patch extends D34590 to check assumption violations.