Skip to content
Open
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
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2726,7 +2726,7 @@ def : MutualExclusions<[AlwaysInline, NotTailCalled]>;
def NoStackProtector : InheritableAttr {
let Spellings = [Clang<"no_stack_protector">, CXX11<"gnu", "no_stack_protector">,
C23<"gnu", "no_stack_protector">, Declspec<"safebuffers">];
let Subjects = SubjectList<[Function]>;
let Subjects = SubjectList<[Function, LocalVar]>;
let Documentation = [NoStackProtectorDocs];
let SimpleHandler = 1;
}
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,14 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
allocaAlignment, D.getName(),
/*ArraySize=*/nullptr, &AllocaAddr);

if (D.hasAttr<NoStackProtectorAttr>()) {
if (auto *AI = dyn_cast<llvm::AllocaInst>(address.getBasePointer())) {
llvm::LLVMContext &Ctx = Builder.getContext();
auto *Operand = llvm::ConstantAsMetadata::get(Builder.getInt32(0));
AI->setMetadata("stack-protector", llvm::MDNode::get(Ctx, {Operand}));
}
}

// Don't emit lifetime markers for MSVC catch parameters. The lifetime of
// the catch parameter starts in the catchpad instruction, and we can't
// insert code in those basic blocks.
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGen/stack-protector-vars.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s

typedef __SIZE_TYPE__ size_t;

int printf(const char * _Format, ...);
char *strcpy(char *s1, const char *s2);

// CHECK: define {{.*}}void @test1
// CHECK: %a = alloca [1000 x i8], align 1, !stack-protector ![[A:.*]]
void test1(const char *msg) {
__attribute__((no_stack_protector))
char a[1000];
strcpy(a, msg);
printf("%s\n", a);
}

// CHECK: define {{.*}}void @test2
// CHECK-NOT: %b = alloca [1000 x i8], align 1, !stack-protector
void test2(const char *msg) {
char b[1000];
strcpy(b, msg);
printf("%s\n", b);
}

// CHECK: ![[A]] = !{i32 0}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
// CHECK-NEXT: NoSanitizeThread (SubjectMatchRule_function)
// CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: NoSplitStack (SubjectMatchRule_function)
// CHECK-NEXT: NoStackProtector (SubjectMatchRule_function)
// CHECK-NEXT: NoStackProtector (SubjectMatchRule_function, SubjectMatchRule_variable_is_local)
// CHECK-NEXT: NoThreadSafetyAnalysis (SubjectMatchRule_function)
// CHECK-NEXT: NoThrow (SubjectMatchRule_hasType_functionType)
// CHECK-NEXT: NoUwtable (SubjectMatchRule_hasType_functionType)
Expand Down
7 changes: 6 additions & 1 deletion clang/test/Sema/no_stack_protector.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
[[clang::no_stack_protector]] void test2(void) {}

void __attribute__((no_stack_protector)) foo(void) {}
int __attribute__((no_stack_protector)) var; // expected-warning {{'no_stack_protector' attribute only applies to functions}}
int __attribute__((no_stack_protector)) var; // expected-warning {{'no_stack_protector' attribute only applies to functions and local variables}}
void __attribute__((no_stack_protector(2))) bar(void) {} // expected-error {{'no_stack_protector' attribute takes no arguments}}

void func()
{
int __attribute__((no_stack_protector)) localvar;
}
Loading