Add a no_stack_protector function attribute to localize the effect

of disabling stack protection on a function-by-function level, as
opposed to per source file.
This commit is contained in:
christos 2011-05-08 01:49:32 +00:00
parent e1b3bebc56
commit b58828d4bd
3 changed files with 45 additions and 3 deletions

View File

@ -529,6 +529,8 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
bool *);
static tree handle_no_instrument_function_attribute (tree *, tree,
tree, int, bool *);
static tree handle_no_stack_protector_function_attribute (tree *, tree,
tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
@ -608,6 +610,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_weakref_attribute },
{ "no_instrument_function", 0, 0, true, false, false,
handle_no_instrument_function_attribute },
{ "no_stack_protector", 0, 0, true, false, false,
handle_no_stack_protector_function_attribute },
{ "malloc", 0, 0, true, false, false,
handle_malloc_attribute },
{ "returns_twice", 0, 0, true, false, false,
@ -5051,6 +5055,32 @@ handle_no_instrument_function_attribute (tree *node, tree name,
return NULL_TREE;
}
/* Handle a "no_instrument_function" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_no_stack_protector_function_attribute (tree *node, tree name,
tree ARG_UNUSED (args),
int ARG_UNUSED (flags),
bool *no_add_attrs)
{
tree decl = *node;
if (TREE_CODE (decl) != FUNCTION_DECL)
{
error ("%J%qE attribute applies only to functions", decl, name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
error ("%Jcan%'t set %qE attribute after definition", decl, name);
*no_add_attrs = true;
}
else
DECL_NO_STACK_PROTECTOR_FUNCTION (decl) = 1;
return NULL_TREE;
}
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */

View File

@ -862,6 +862,9 @@ stack_protect_decl_phase (tree decl)
unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
int ret = 0;
if (DECL_NO_STACK_PROTECTOR_FUNCTION(decl))
return ret;
if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
has_short_buffer = true;
@ -939,6 +942,7 @@ static void
expand_used_vars (void)
{
tree t, outer_block = DECL_INITIAL (current_function_decl);
bool stack_protect_func = !DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl);
/* Compute the phase of the stack frame for this function. */
{
@ -1008,7 +1012,7 @@ 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)
if (flag_stack_protect && stack_protect_func)
add_stack_protection_conflicts ();
/* Now that we have collected all stack variables, and have computed a
@ -1020,7 +1024,8 @@ expand_used_vars (void)
/* There are several conditions under which we should create a
stack guard: protect-all, alloca used, protected decls present. */
if (flag_stack_protect == 2
if (stack_protect_func)
if (flag_stack_protect == 2
|| (flag_stack_protect
&& (current_function_calls_alloca || has_protected_decls)))
create_stack_guard ();
@ -1595,7 +1600,8 @@ tree_expand_cfg (void)
expand_used_vars ();
/* Honor stack protection warnings. */
if (warn_stack_protect)
if (warn_stack_protect &&
!DECL_NO_STACK_PROTECTOR_FUNCTION (current_function_decl))
{
if (current_function_calls_alloca)
warning (0, "not protecting local variables: variable length buffer");

View File

@ -2680,6 +2680,11 @@ struct tree_decl_non_common GTY(())
#define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.no_instrument_function_entry_exit)
/* Used in FUNCTION_DECLs to indicate that the function should not be stack
protected */
#define DECL_NO_STACK_PROTECTOR_FUNCTION(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.no_stack_protector_function)
/* Used in FUNCTION_DECLs to indicate that limit-stack-* should be
disabled in this function. */
#define DECL_NO_LIMIT_STACK(NODE) \
@ -2746,6 +2751,7 @@ struct tree_function_decl GTY(())
unsigned regdecl_flag : 1;
unsigned inline_flag : 1;
unsigned no_instrument_function_entry_exit : 1;
unsigned no_stack_protector_function : 1;
unsigned no_limit_stack : 1;
ENUM_BITFIELD(built_in_class) built_in_class : 2;