melver created this revision. melver added reviewers: jfb, pcc, glider. melver requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
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()`, 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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D115440 Files: 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 Index: clang/test/Sema/warn-alloca.c =================================================================== --- clang/test/Sema/warn-alloca.c +++ clang/test/Sema/warn-alloca.c @@ -18,3 +18,10 @@ // 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 +} Index: clang/test/CodeGenCXX/trivial-auto-var-init.cpp =================================================================== --- clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -201,6 +201,20 @@ 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_struct_vla( // ZERO-LABEL: test_struct_vla( // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1686,6 +1686,7 @@ if (SemaBuiltinAllocaWithAlign(TheCall)) return ExprError(); LLVM_FALLTHROUGH; + case Builtin::BI__builtin_alloca_uninitialized: case Builtin::BI__builtin_alloca: Diag(TheCall->getBeginLoc(), diag::warn_alloca) << TheCall->getDirectCallee(); Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -3417,6 +3417,7 @@ 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(); @@ -3427,7 +3428,8 @@ .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); } Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -640,6 +640,7 @@ 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_call_with_static_chain, "v.", "nt")
Index: clang/test/Sema/warn-alloca.c =================================================================== --- clang/test/Sema/warn-alloca.c +++ clang/test/Sema/warn-alloca.c @@ -18,3 +18,10 @@ // 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 +} Index: clang/test/CodeGenCXX/trivial-auto-var-init.cpp =================================================================== --- clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -201,6 +201,20 @@ 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_struct_vla( // ZERO-LABEL: test_struct_vla( // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1686,6 +1686,7 @@ if (SemaBuiltinAllocaWithAlign(TheCall)) return ExprError(); LLVM_FALLTHROUGH; + case Builtin::BI__builtin_alloca_uninitialized: case Builtin::BI__builtin_alloca: Diag(TheCall->getBeginLoc(), diag::warn_alloca) << TheCall->getDirectCallee(); Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -3417,6 +3417,7 @@ 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(); @@ -3427,7 +3428,8 @@ .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); } Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -640,6 +640,7 @@ 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_call_with_static_chain, "v.", "nt")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits