Author: Marco Elver Date: 2022-01-12T15:13:10+01:00 New Revision: 732ad8ea62edc403727af57537b5d83dcfa937aa
URL: https://github.com/llvm/llvm-project/commit/732ad8ea62edc403727af57537b5d83dcfa937aa DIFF: https://github.com/llvm/llvm-project/commit/732ad8ea62edc403727af57537b5d83dcfa937aa.diff LOG: [clang][auto-init] Provide __builtin_alloca*_uninitialized variants When `-ftrivial-auto-var-init=` is enabled, allocas unconditionally receive auto-initialization since [1]. In certain cases, it turns out, this is causing problems. For example, when using alloca to add a random stack offset, as the Linux kernel does on syscall entry [2]. In this case, none of the alloca'd stack memory is ever used, and initializing it should be controllable; furthermore, it is not always possible to safely call memset (see [2]). Introduce `__builtin_alloca_uninitialized()` (and `__builtin_alloca_with_align_uninitialized`), which never performs initialization when `-ftrivial-auto-var-init=` is enabled. [1] https://reviews.llvm.org/D60548 [2] https://lkml.kernel.org/r/ybhtkujeejzcl...@elver.google.com Reviewed By: glider Differential Revision: https://reviews.llvm.org/D115440 Added: Modified: clang/include/clang/Basic/Builtins.def clang/lib/CodeGen/CGBuiltin.cpp clang/lib/Sema/SemaChecking.cpp clang/test/CodeGenCXX/trivial-auto-var-init.cpp clang/test/Sema/warn-alloca.c Removed: ################################################################################ diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index bfaa7e9f5a9fa..c7c47cf99abac 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -641,7 +641,9 @@ BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nct") BUILTIN(__builtin_convertvector, "v." , "nct") BUILTIN(__builtin_alloca, "v*z" , "Fn") +BUILTIN(__builtin_alloca_uninitialized, "v*z", "Fn") BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn") +BUILTIN(__builtin_alloca_with_align_uninitialized, "v*zIz", "Fn") BUILTIN(__builtin_call_with_static_chain, "v.", "nt") BUILTIN(__builtin_elementwise_abs, "v.", "nct") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7b5d202afbba2..e9dd41a7daa10 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3427,6 +3427,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BIalloca: case Builtin::BI_alloca: + case Builtin::BI__builtin_alloca_uninitialized: case Builtin::BI__builtin_alloca: { Value *Size = EmitScalarExpr(E->getArg(0)); const TargetInfo &TI = getContext().getTargetInfo(); @@ -3437,10 +3438,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, .getAsAlign(); AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); AI->setAlignment(SuitableAlignmentInBytes); - initializeAlloca(*this, AI, Size, SuitableAlignmentInBytes); + if (BuiltinID != Builtin::BI__builtin_alloca_uninitialized) + initializeAlloca(*this, AI, Size, SuitableAlignmentInBytes); return RValue::get(AI); } + case Builtin::BI__builtin_alloca_with_align_uninitialized: case Builtin::BI__builtin_alloca_with_align: { Value *Size = EmitScalarExpr(E->getArg(0)); Value *AlignmentInBitsValue = EmitScalarExpr(E->getArg(1)); @@ -3450,7 +3453,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, CGM.getContext().toCharUnitsFromBits(AlignmentInBits).getAsAlign(); AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size); AI->setAlignment(AlignmentInBytes); - initializeAlloca(*this, AI, Size, AlignmentInBytes); + if (BuiltinID != Builtin::BI__builtin_alloca_with_align_uninitialized) + initializeAlloca(*this, AI, Size, AlignmentInBytes); return RValue::get(AI); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 908cb78fbb0a7..d067ac31dc1e8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1750,10 +1750,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return ExprError(); break; case Builtin::BI__builtin_alloca_with_align: + case Builtin::BI__builtin_alloca_with_align_uninitialized: if (SemaBuiltinAllocaWithAlign(TheCall)) return ExprError(); LLVM_FALLTHROUGH; case Builtin::BI__builtin_alloca: + case Builtin::BI__builtin_alloca_uninitialized: Diag(TheCall->getBeginLoc(), diag::warn_alloca) << TheCall->getDirectCallee(); break; diff --git a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp index 513222cb3f1d1..58fba5d96b577 100644 --- a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -201,6 +201,34 @@ void test_alloca_with_align(int size) { used(ptr); } +// UNINIT-LABEL: test_alloca_uninitialized( +// ZERO-LABEL: test_alloca_uninitialized( +// ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 +// ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] +// ZERO-NOT: call void @llvm.memset +// PATTERN-LABEL: test_alloca_uninitialized( +// PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 +// PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] +// PATTERN-NOT: call void @llvm.memset +void test_alloca_uninitialized(int size) { + void *ptr = __builtin_alloca_uninitialized(size); + used(ptr); +} + +// UNINIT-LABEL: test_alloca_with_align_uninitialized( +// ZERO-LABEL: test_alloca_with_align_uninitialized( +// ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 +// ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 +// ZERO-NOT: call void @llvm.memset +// PATTERN-LABEL: test_alloca_with_align_uninitialized( +// PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 +// PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 +// PATTERN-NOT: call void @llvm.memset +void test_alloca_with_align_uninitialized(int size) { + void *ptr = __builtin_alloca_with_align_uninitialized(size, 1024); + used(ptr); +} + // UNINIT-LABEL: test_struct_vla( // ZERO-LABEL: test_struct_vla( // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 diff --git a/clang/test/Sema/warn-alloca.c b/clang/test/Sema/warn-alloca.c index 0990e11ef2fa2..07fe0f920304d 100644 --- a/clang/test/Sema/warn-alloca.c +++ b/clang/test/Sema/warn-alloca.c @@ -18,3 +18,17 @@ void test2(int a) { // expected-warning@-2 {{use of function '__builtin_alloca_with_align' is discouraged; there is no way to check for failure but failure may still occur, resulting in a possibly exploitable security vulnerability}} #endif } + +void test3(int a) { + __builtin_alloca_uninitialized(a); +#ifndef SILENCE + // expected-warning@-2 {{use of function '__builtin_alloca_uninitialized' is discouraged; there is no way to check for failure but failure may still occur, resulting in a possibly exploitable security vulnerability}} +#endif +} + +void test4(int a) { + __builtin_alloca_with_align_uninitialized(a, 32); +#ifndef SILENCE + // expected-warning@-2 {{use of function '__builtin_alloca_with_align_uninitialized' is discouraged; there is no way to check for failure but failure may still occur, resulting in a possibly exploitable security vulnerability}} +#endif +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits