[gcc(refs/users/marxin/heads/implement-no_stack_protect-attribute-v4)] Implement no_stack_protector attribute.
Martin Liska
marxin@gcc.gnu.org
Thu Oct 22 07:15:54 GMT 2020
https://gcc.gnu.org/g:cb35a5e5839a8fbfd95dda4e9cfecaf99c326385
commit cb35a5e5839a8fbfd95dda4e9cfecaf99c326385
Author: Martin Liska <mliska@suse.cz>
Date: Fri May 15 14:42:12 2020 +0200
Implement no_stack_protector attribute.
gcc/ChangeLog:
2020-05-18 Martin Liska <mliska@suse.cz>
PR c/94722
* cfgexpand.c (stack_protect_decl_phase):
Guard with lookup_attribute("no_stack_protector") at
various places.
(expand_used_vars): Likewise here.
* doc/extend.texi: Document no_stack_protector attribute.
gcc/ada/ChangeLog:
2020-05-18 Martin Liska <mliska@suse.cz>
PR c/94722
* gcc-interface/utils.c (handle_no_stack_protect_attribute):
New.
(handle_stack_protect_attribute): Add error message for a
no_stack_protector function.
gcc/c-family/ChangeLog:
2020-05-18 Martin Liska <mliska@suse.cz>
PR c/94722
* c-attribs.c (handle_no_stack_protect_function_attribute): New.
(handle_stack_protect_attribute): Add error message for a
no_stack_protector function.
gcc/testsuite/ChangeLog:
2020-05-18 Martin Liska <mliska@suse.cz>
PR c/94722
* g++.dg/no-stack-protect-attr-2.C: New test.
* g++.dg/no-stack-protect-attr-3.C: New test.
* g++.dg/no-stack-protect-attr.C: New test.
Diff:
---
gcc/ada/gcc-interface/utils.c | 31 +++++++++-
gcc/c-family/c-attribs.c | 32 +++++++++-
gcc/cfgexpand.c | 82 ++++++++++++++------------
gcc/doc/extend.texi | 4 ++
gcc/testsuite/g++.dg/no-stack-protect-attr-2.C | 7 +++
gcc/testsuite/g++.dg/no-stack-protect-attr-3.C | 23 ++++++++
gcc/testsuite/g++.dg/no-stack-protect-attr.C | 16 +++++
7 files changed, 154 insertions(+), 41 deletions(-)
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 048a0cf13b4..d50872f81b0 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -92,6 +92,7 @@ static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
+static tree handle_no_stack_protector_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
@@ -116,6 +117,13 @@ static const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
{ NULL , false, false, false }
};
+static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
+{
+ { "stack_protect", true, false, false },
+ { "no_stack_protector", true, false, false },
+ { NULL, false, false, false },
+};
+
/* Fake handler for attributes we don't properly support, typically because
they'd require dragging a lot of the common-c front-end circuitry. */
static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
@@ -141,7 +149,11 @@ const struct attribute_spec gnat_internal_attribute_table[] =
{ "noreturn", 0, 0, true, false, false, false,
handle_noreturn_attribute, NULL },
{ "stack_protect",0, 0, true, false, false, false,
- handle_stack_protect_attribute, NULL },
+ handle_stack_protect_attribute,
+ attr_stack_protect_exclusions },
+ { "no_stack_protector",0, 0, true, false, false, false,
+ handle_no_stack_protector_attribute,
+ attr_stack_protect_exclusions },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute, NULL },
{ "noclone", 0, 0, true, false, false, false,
@@ -6560,6 +6572,23 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
+/* Handle a "no_stack_protector" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_stack_protector_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 8283e959c89..a3b2b3d58bd 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -65,6 +65,8 @@ static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
bool *);
static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
+static tree handle_no_stack_protector_function_attribute (tree *, tree,
+ tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *);
@@ -248,6 +250,14 @@ static const struct attribute_spec::exclusions attr_noinit_exclusions[] =
ATTR_EXCL (NULL, false, false, false),
};
+static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
+{
+ ATTR_EXCL ("stack_protect", true, false, false),
+ ATTR_EXCL ("no_stack_protector", true, false, false),
+ ATTR_EXCL (NULL, false, false, false),
+};
+
+
/* Table of machine-independent attributes common to all C-like languages.
Current list of processed common attributes: nonnull. */
@@ -275,7 +285,11 @@ const struct attribute_spec c_common_attribute_table[] =
{ "volatile", 0, 0, true, false, false, false,
handle_noreturn_attribute, NULL },
{ "stack_protect", 0, 0, true, false, false, false,
- handle_stack_protect_attribute, NULL },
+ handle_stack_protect_attribute,
+ attr_stack_protect_exclusions },
+ { "no_stack_protector", 0, 0, true, false, false, false,
+ handle_no_stack_protector_function_attribute,
+ attr_stack_protect_exclusions },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute,
attr_noinline_exclusions },
@@ -1156,6 +1170,22 @@ handle_stack_protect_attribute (tree *node, tree name, tree, int,
return NULL_TREE;
}
+/* Handle a "no_stack_protector" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_stack_protector_function_attribute (tree *node, tree name, tree,
+ int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "noipa" attribute; arguments as in
struct attribute_spec.handler. */
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 2ac9aef389a..f3f17d38f9e 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1831,11 +1831,12 @@ stack_protect_decl_phase (tree decl)
if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
has_short_buffer = true;
- if (flag_stack_protect == SPCT_FLAG_ALL
- || flag_stack_protect == SPCT_FLAG_STRONG
- || (flag_stack_protect == SPCT_FLAG_EXPLICIT
- && lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl))))
+ tree attribs = DECL_ATTRIBUTES (current_function_decl);
+ if (!lookup_attribute ("no_stack_protector", attribs)
+ && (flag_stack_protect == SPCT_FLAG_ALL
+ || flag_stack_protect == SPCT_FLAG_STRONG
+ || (flag_stack_protect == SPCT_FLAG_EXPLICIT
+ && lookup_attribute ("stack_protect", attribs))))
{
if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
&& !(bits & SPCT_HAS_AGGREGATE))
@@ -2136,6 +2137,7 @@ expand_used_vars (void)
set are actually used by the optimized function. Lay them out. */
expand_used_vars_for_block (outer_block, true);
+ tree attribs = DECL_ATTRIBUTES (current_function_decl);
if (stack_vars_num > 0)
{
bool has_addressable_vars = false;
@@ -2145,10 +2147,10 @@ expand_used_vars (void)
/* If stack protection is enabled, we don't share space between
vulnerable data and non-vulnerable data. */
if (flag_stack_protect != 0
+ && !lookup_attribute ("no_stack_protector", attribs)
&& (flag_stack_protect != SPCT_FLAG_EXPLICIT
|| (flag_stack_protect == SPCT_FLAG_EXPLICIT
- && lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl)))))
+ && lookup_attribute ("stack_protect", attribs))))
has_addressable_vars = add_stack_protection_conflicts ();
if (flag_stack_protect == SPCT_FLAG_STRONG && has_addressable_vars)
@@ -2161,38 +2163,40 @@ expand_used_vars (void)
dump_stack_var_partition ();
}
- switch (flag_stack_protect)
- {
- case SPCT_FLAG_ALL:
- create_stack_guard ();
- break;
- case SPCT_FLAG_STRONG:
- if (gen_stack_protect_signal
- || cfun->calls_alloca
- || has_protected_decls
- || lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl)))
+ if (!lookup_attribute ("no_stack_protector", attribs))
+ switch (flag_stack_protect)
+ {
+ case SPCT_FLAG_ALL:
create_stack_guard ();
- break;
+ break;
- case SPCT_FLAG_DEFAULT:
- if (cfun->calls_alloca
- || has_protected_decls
- || lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl)))
- create_stack_guard ();
- break;
+ case SPCT_FLAG_STRONG:
+ if (gen_stack_protect_signal
+ || cfun->calls_alloca
+ || has_protected_decls
+ || lookup_attribute ("stack_protect",
+ DECL_ATTRIBUTES (current_function_decl)))
+ create_stack_guard ();
+ break;
- case SPCT_FLAG_EXPLICIT:
- if (lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl)))
- create_stack_guard ();
- break;
+ case SPCT_FLAG_DEFAULT:
+ if (cfun->calls_alloca
+ || has_protected_decls
+ || lookup_attribute ("stack_protect",
+ DECL_ATTRIBUTES (current_function_decl)))
+ create_stack_guard ();
+ break;
- default:
- break;
- }
+ case SPCT_FLAG_EXPLICIT:
+ if (lookup_attribute ("stack_protect",
+ DECL_ATTRIBUTES (current_function_decl)))
+ create_stack_guard ();
+ break;
+
+ default:
+ break;
+ }
/* Assign rtl to each variable based on these partitions. */
if (stack_vars_num > 0)
@@ -2213,11 +2217,11 @@ expand_used_vars (void)
expand_stack_vars (stack_protect_decl_phase_1, &data);
/* Phase 2 contains other kinds of arrays. */
- if (flag_stack_protect == SPCT_FLAG_ALL
- || flag_stack_protect == SPCT_FLAG_STRONG
- || (flag_stack_protect == SPCT_FLAG_EXPLICIT
- && lookup_attribute ("stack_protect",
- DECL_ATTRIBUTES (current_function_decl))))
+ if (!lookup_attribute ("no_stack_protector", attribs)
+ && (flag_stack_protect == SPCT_FLAG_ALL
+ || flag_stack_protect == SPCT_FLAG_STRONG
+ || (flag_stack_protect == SPCT_FLAG_EXPLICIT
+ && lookup_attribute ("stack_protect", attribs))))
expand_stack_vars (stack_protect_decl_phase_2, &data);
}
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 62549b02452..4a7c85822a7 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3680,6 +3680,10 @@ This attribute adds stack protection code to the function if
flags @option{-fstack-protector}, @option{-fstack-protector-strong}
or @option{-fstack-protector-explicit} are set.
+@item no_stack_protector
+@cindex @code{no_stack_protector} function attribute
+This attribute prevents stack protection code for the function.
+
@item target (@var{string}, @dots{})
@cindex @code{target} function attribute
Multiple target back ends implement the @code{target} attribute
diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C b/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C
new file mode 100644
index 00000000000..d5450306c3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/no-stack-protect-attr-2.C
@@ -0,0 +1,7 @@
+/* PR c/94722 */
+/* { dg-do compile } */
+
+int __attribute__((no_stack_protector, stack_protect)) c() /* { dg-warning "ignoring attribute 'stack_protect' because it conflicts with attribute 'no_stack_protect'" } */
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C b/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C
new file mode 100644
index 00000000000..dd9cd4991b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/no-stack-protect-attr-3.C
@@ -0,0 +1,23 @@
+/* PR c/94722 */
+/* Test that stack protection is disabled via no_stack_protector attribute. */
+
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fstack-protector-explicit" } */
+
+/* { dg-do compile } */
+
+int __attribute__((no_stack_protector)) foo()
+{
+ int a;
+ char b[34];
+ return 0;
+}
+
+int __attribute__((stack_protect)) bar()
+{
+ int a;
+ char b[34];
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "stack_chk_fail" 1 } } */
diff --git a/gcc/testsuite/g++.dg/no-stack-protect-attr.C b/gcc/testsuite/g++.dg/no-stack-protect-attr.C
new file mode 100644
index 00000000000..e5105bf9478
--- /dev/null
+++ b/gcc/testsuite/g++.dg/no-stack-protect-attr.C
@@ -0,0 +1,16 @@
+/* PR c/94722 */
+/* Test that stack protection is disabled via no_stack_protector attribute. */
+
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fstack-protector-all" } */
+
+/* { dg-do compile } */
+
+int __attribute__((no_stack_protector)) c()
+{
+ int a;
+ char b[34];
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "stack_chk_fail" } } */
More information about the Gcc-cvs
mailing list