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-protector-attr-2.C: New test. * g++.dg/no-stack-protector-attr-3.C: New test. * g++.dg/no-stack-protector-attr.C: New test.
This commit is contained in:
parent
5a99796b85
commit
346b302d09
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_protector'" } */
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -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 } } */
|
|
@ -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" } } */
|
Loading…
Reference in New Issue