Skip to content

[CodeGen] -fsanitize=alignment: add cl::opt sanitize-alignment-builtin to disable memcpy instrumentation #69240

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

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ using namespace clang;
using namespace CodeGen;
using namespace llvm;

static llvm::cl::opt<bool> ClSanitizeAlignmentBuiltin(
"sanitize-alignment-builtin", llvm::cl::Hidden,
llvm::cl::desc("Instrument builtin functions for -fsanitize=alignment"),
llvm::cl::init(true));

Comment on lines +69 to +73
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you using a cl::opt here rather than a proper CodeGenOption? We generally don't use cl::opt in clang and want our options to be provided via our option structs instead, so that clang can be used as a library.

Copy link
Member Author

@MaskRay MaskRay Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I acknowledge that cl::opt is discouraged (clang/lib has very few of them). This is a temporary workaround (so that our users can perform cleanups without being blocked) and should not be in Clang for too long. I'll revert this after ~two months, assuming that rolling update users (like us) have caught up on the change and tested their code bases. Given how large our code base is and how few (relatively) problems identified, I reasonably expect that the effect of instrumenting memcpy is small and we don't really need a driver option or cc1 option.

I modeled this after cl::opt<bool> ClSanitizeOnOptimizerEarlyEP in clang/lib/CodeGen/BackendUtil.cpp and thought that cl::opt might look more experimental than a cc1 option...

static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
Align AlignmentInBytes) {
ConstantInt *Byte;
Expand Down Expand Up @@ -2788,7 +2793,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD,
ParmNum);

if (SanOpts.has(SanitizerKind::Alignment)) {
if (SanOpts.has(SanitizerKind::Alignment) && ClSanitizeAlignmentBuiltin) {
SanitizerSet SkippedChecks;
SkippedChecks.set(SanitizerKind::All);
SkippedChecks.clear(SanitizerKind::Alignment);
Expand Down
45 changes: 31 additions & 14 deletions clang/test/CodeGen/catch-undef-behavior.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-UBSAN
// RUN: %clang_cc1 -fsanitize-trap=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-COMMON --check-prefix=CHECK-TRAP
// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-UBSAN,CHECK-ALIGNMENT-BUILTIN
// RUN: %clang_cc1 -fsanitize-trap=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-ALIGNMENT-BUILTIN,CHECK-TRAP
// RUN: %clang_cc1 -fsanitize=signed-integer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-OVERFLOW
/// A variant of CHECK-UBSAN with -sanitize-alignment-builtin disabled
// RUN: %clang_cc1 -fsanitize=alignment,null,object-size,shift-base,shift-exponent,return,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -fsanitize-recover=alignment,null,object-size,shift-base,shift-exponent,signed-integer-overflow,vla-bound,float-cast-overflow,integer-divide-by-zero,bool,returns-nonnull-attribute,nonnull-attribute -emit-llvm %s -o - -triple x86_64-linux-gnu -mllvm -sanitize-alignment-builtin=0 | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-UBSAN-NO-ALIGNMENT-BUILTIN

// CHECK-UBSAN: @[[INT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" }

Expand Down Expand Up @@ -363,11 +365,13 @@ extern void *memcpy(void *, const void *, unsigned long) __attribute__((nonnull(
void call_memcpy_nonnull(void *p, void *q, int sz) {
// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON-NOT: call

// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON-NOT: call

Expand All @@ -379,18 +383,23 @@ void call_memcpy_nonnull(void *p, void *q, int sz) {
void call_memcpy(long *p, short *q, int sz) {
// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON: and i64 %[[#]], 7, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 7, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(ptr @[[LINE_1600]]
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-UBSAN-DISABLE-BUILTIN: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON: and i64 %[[#]], 1, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 1, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %0, ptr align 2 %1, i64 %conv, i1 false)
Expand All @@ -405,14 +414,16 @@ void call_memcpy(long *p, short *q, int sz) {

// CHECK-COMMON-LABEL: define{{.*}} void @call_memcpy_inline(
void call_memcpy_inline(long *p, short *q) {
// CHECK-COMMON: and i64 %[[#]], 7, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 7, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: and i64 %[[#]], 1, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 1, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 %0, ptr align 2 %1, i64 2, i1 false)
Expand All @@ -425,10 +436,12 @@ extern void *memmove(void *, const void *, unsigned long) __attribute__((nonnull
void call_memmove_nonnull(void *p, void *q, int sz) {
// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)

// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
memmove(p, q, sz);
}
Expand All @@ -437,18 +450,22 @@ void call_memmove_nonnull(void *p, void *q, int sz) {
void call_memmove(long *p, short *q, int sz) {
// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON: and i64 %[[#]], 7, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 7, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: icmp ne ptr {{.*}}, null
// CHECK-UBSAN: call void @__ubsan_handle_nonnull_arg(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN: call void @__ubsan_handle_nonnull_arg(
// CHECK-TRAP: call void @llvm.ubsantrap(i8 16)
// CHECK-COMMON: and i64 %[[#]], 1, !nosanitize
// CHECK-COMMON: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: and i64 %[[#]], 1, !nosanitize
// CHECK-ALIGNMENT-BUILTIN: icmp eq i64 %[[#]], 0, !nosanitize
// CHECK-UBSAN: call void @__ubsan_handle_type_mismatch_v1(
// CHECK-UBSAN-NO-ALIGNMENT-BUILTIN-NOT: call
// CHECK-TRAP: call void @llvm.ubsantrap(i8 22)

// CHECK-COMMON: call void @llvm.memmove.p0.p0.i64(ptr align 8 %0, ptr align 2 %1, i64 %conv, i1 false)
Expand Down