The access attribute handler doesn't check to make sure the mode argument is an identifier and readily accepts string arguments which are assumed to be the condensed internal representation the user attribute is translated to. This can cause all sorts of unintended behavior when the user supplies a bogus string, either by accident or in an effort to break things.
The attached patch tightens up the attribute handler to reject strings and any other modes that aren't the expected indentifiers. It distinguishes the internal strings by introducing a new flag, ATTR_FLAG_INTERNAL, and calling decl_attributes() with it. Martin
PR middle-end/97879 - ICE on invalid mode in attribute access gcc/c-family/ChangeLog: PR middle-end/97879 * c-attribs.c (handle_access_attribute): Handle ATTR_FLAG_INTERNAL. Error out on invalid modes. gcc/ChangeLog: PR middle-end/97879 * tree-core.h (enum attribute_flags): Add ATTR_FLAG_INTERNAL. gcc/testsuite/ChangeLog: PR middle-end/97879 * gcc.dg/attr-access-3.c: New test. diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index b979fbcc0c6..813b90a465c 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -4289,8 +4289,8 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr, the attribute and its arguments into a string. */ static tree -handle_access_attribute (tree node[3], tree name, tree args, - int ARG_UNUSED (flags), bool *no_add_attrs) +handle_access_attribute (tree node[3], tree name, tree args, int flags, + bool *no_add_attrs) { tree attrs = TYPE_ATTRIBUTES (*node); tree type = *node; @@ -4336,15 +4336,19 @@ handle_access_attribute (tree node[3], tree name, tree args, /* Recursively call self to "replace" the documented/external form of the attribute with the condensend internal form. */ - decl_attributes (node, axsat, flags); + decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL); return NULL_TREE; } - /* This is a recursive call to handle the condensed internal form - of the attribute (see below). Since all validation has been - done simply return here, accepting the attribute as is. */ - *no_add_attrs = false; - return NULL_TREE; + if (flags & ATTR_FLAG_INTERNAL) + { + /* This is a recursive call to handle the condensed internal + form of the attribute (see below). Since all validation + has been done simply return here, accepting the attribute + as is. */ + *no_add_attrs = false; + return NULL_TREE; + } } /* Set to true when the access mode has the form of a function call @@ -4363,6 +4367,13 @@ handle_access_attribute (tree node[3], tree name, tree args, access_mode = DECL_NAME (access_mode); funcall = true; } + else if (TREE_CODE (access_mode) != IDENTIFIER_NODE) + { + error ("attribute %qE mode %qE is not an identifier; expected one of " + "%qs, %qs, %qs, or %qs", name, access_mode, + "read_only", "read_write", "write_only", "none"); + return NULL_TREE; + } const char* const access_str = IDENTIFIER_POINTER (access_mode); const char *ps = access_str; @@ -4573,7 +4584,7 @@ handle_access_attribute (tree node[3], tree name, tree args, /* Recursively call self to "replace" the documented/external form of the attribute with the condensed internal form. */ - decl_attributes (node, new_attrs, flags); + decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL); return NULL_TREE; } diff --git a/gcc/testsuite/gcc.dg/attr-access-3.c b/gcc/testsuite/gcc.dg/attr-access-3.c new file mode 100644 index 00000000000..8c793bf4b82 --- /dev/null +++ b/gcc/testsuite/gcc.dg/attr-access-3.c @@ -0,0 +1,18 @@ +/* PR middle-end/97879 - ICE on invalid mode in attribute access + { dg-do compile } + { dg-options "-Wall" } */ + +#define A(...) __attribute__ ((access (__VA_ARGS__))) + +A (" ", 1) void f1 (int *); // { dg-error "attribute 'access' mode '\" \"' is not an identifier; expected one of 'read_only', 'read_write', 'write_only', or 'none'" } + void f1 (int *); + + +A ("none", 1) void f2 (char *); // { dg-error "not an identifier" } + void f2 (char *); + +A (1) void f3 (); // { dg-error "not an identifier" } + +A (1, 2) void f4 (); // { dg-error "not an identifier" } +A (2., 3.) void f5 (); // { dg-error "not an identifier" } + diff --git a/gcc/tree-core.h b/gcc/tree-core.h index c9280a8d3b1..313a6af2253 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -859,7 +859,10 @@ enum attribute_flags { are not in fact compatible with the function type. */ ATTR_FLAG_BUILT_IN = 16, /* A given attribute has been parsed as a C++-11 attribute. */ - ATTR_FLAG_CXX11 = 32 + ATTR_FLAG_CXX11 = 32, + /* The attribute handler is being invoked with an internal argument + that may not otherwise be valid when specified in source code. */ + ATTR_FLAG_INTERNAL = 64 }; /* Types used to represent sizes. */