diff options
Diffstat (limited to 'gcc/c-family/c-attribs.c')
-rw-r--r-- | gcc/c-family/c-attribs.c | 110 |
1 files changed, 96 insertions, 14 deletions
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 695c58c0a14..2b6845f2cbd 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -51,8 +51,11 @@ static tree handle_common_attribute (tree *, tree, tree, int, bool *); static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); static tree handle_hot_attribute (tree *, tree, tree, int, bool *); static tree handle_cold_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *); static tree handle_no_sanitize_address_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_sanitize_thread_attribute (tree *, tree, tree, + int, bool *); static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree, int, bool *); static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int, @@ -285,11 +288,14 @@ const struct attribute_spec c_common_attribute_table[] = 0, 0, true, false, false, handle_no_address_safety_analysis_attribute, false }, + { "no_sanitize", 1, 1, true, false, false, + handle_no_sanitize_attribute, + false }, { "no_sanitize_address", 0, 0, true, false, false, handle_no_sanitize_address_attribute, false }, { "no_sanitize_thread", 0, 0, true, false, false, - handle_no_sanitize_address_attribute, + handle_no_sanitize_thread_attribute, false }, { "no_sanitize_undefined", 0, 0, true, false, false, handle_no_sanitize_undefined_attribute, @@ -547,22 +553,98 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } -/* Handle a "no_sanitize_address" attribute; arguments as in +/* Add FLAGS for a function NODE to no_sanitize_flags in DECL_ATTRIBUTES. */ + +void +add_no_sanitize_value (tree node, unsigned int flags) +{ + tree attr = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (node)); + if (attr) + { + unsigned int old_value = tree_to_uhwi (TREE_VALUE (attr)); + flags |= old_value; + + if (flags == old_value) + return; + + TREE_VALUE (attr) = build_int_cst (unsigned_type_node, flags); + } + else + DECL_ATTRIBUTES (node) + = tree_cons (get_identifier ("no_sanitize"), + build_int_cst (unsigned_type_node, flags), + DECL_ATTRIBUTES (node)); +} + +/* Handle a "no_sanitize" attribute; arguments as in struct attribute_spec.handler. */ static tree -handle_no_sanitize_address_attribute (tree *node, tree name, tree, int, - bool *no_add_attrs) +handle_no_sanitize_attribute (tree *node, tree name, tree args, int, + bool *no_add_attrs) { + *no_add_attrs = true; + tree id = TREE_VALUE (args); if (TREE_CODE (*node) != FUNCTION_DECL) { warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; + return NULL_TREE; + } + + if (TREE_CODE (id) != STRING_CST) + { + error ("no_sanitize argument not a string"); + return NULL_TREE; + } + + char *error_value = NULL; + char *string = ASTRDUP (TREE_STRING_POINTER (id)); + unsigned int flags = parse_no_sanitize_attribute (string, &error_value); + + if (error_value) + { + error ("wrong argument: \"%s\"", error_value); + return NULL_TREE; } + add_no_sanitize_value (*node, flags); + + return NULL_TREE; +} + +/* Handle a "no_sanitize_address" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_sanitize_address_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + *no_add_attrs = true; + if (TREE_CODE (*node) != FUNCTION_DECL) + warning (OPT_Wattributes, "%qE attribute ignored", name); + else + add_no_sanitize_value (*node, SANITIZE_ADDRESS); + + return NULL_TREE; +} + +/* Handle a "no_sanitize_thread" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_sanitize_thread_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + *no_add_attrs = true; + if (TREE_CODE (*node) != FUNCTION_DECL) + warning (OPT_Wattributes, "%qE attribute ignored", name); + else + add_no_sanitize_value (*node, SANITIZE_THREAD); + return NULL_TREE; } + /* Handle a "no_address_safety_analysis" attribute; arguments as in struct attribute_spec.handler. */ @@ -570,13 +652,12 @@ static tree handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { + *no_add_attrs = true; if (TREE_CODE (*node) != FUNCTION_DECL) warning (OPT_Wattributes, "%qE attribute ignored", name); - else if (!lookup_attribute ("no_sanitize_address", DECL_ATTRIBUTES (*node))) - DECL_ATTRIBUTES (*node) - = tree_cons (get_identifier ("no_sanitize_address"), - NULL_TREE, DECL_ATTRIBUTES (*node)); - *no_add_attrs = true; + else + add_no_sanitize_value (*node, SANITIZE_ADDRESS); + return NULL_TREE; } @@ -587,11 +668,12 @@ static tree handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { + *no_add_attrs = true; if (TREE_CODE (*node) != FUNCTION_DECL) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } + warning (OPT_Wattributes, "%qE attribute ignored", name); + else + add_no_sanitize_value (*node, + SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); return NULL_TREE; } |