diff mbox

[C] Don't accept invalid attribute-list (PR c/67964)

Message ID 20151020144554.GW13672@redhat.com
State New
Headers show

Commit Message

Marek Polacek Oct. 20, 2015, 2:45 p.m. UTC
Joseph noticed that we were wrongly accepting multiple attributes without
commas.  Thus fixed by breaking out of the loop when parsing the attributes --
if we don't see a comma after an attribute, then the next tokens must be )); if
not, then the attribute is invalid.  I've also added a few more comments.

(I think it would be nicer to model the code after C++ and introduce
c_parser_attributes_list, but the following is enough to fix the bug.)

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-10-20  Marek Polacek  <polacek@redhat.com>

	PR c/67964
	* c-parser.c (c_parser_attributes): Break out of the loop if the
	token after an attribute isn't a comma.

	* gcc.dg/pr67964.c: New test.


	Marek

Comments

Joseph Myers Oct. 20, 2015, 4:50 p.m. UTC | #1
On Tue, 20 Oct 2015, Marek Polacek wrote:

> Joseph noticed that we were wrongly accepting multiple attributes without
> commas.  Thus fixed by breaking out of the loop when parsing the attributes --
> if we don't see a comma after an attribute, then the next tokens must be )); if
> not, then the attribute is invalid.  I've also added a few more comments.
> 
> (I think it would be nicer to model the code after C++ and introduce
> c_parser_attributes_list, but the following is enough to fix the bug.)
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

OK.
diff mbox

Patch

diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index 704ebc6..e7b8440 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -3965,7 +3965,9 @@  c_parser_attributes (c_parser *parser)
       /* ??? Follow the C++ parser rather than using the
 	 lex_untranslated_string kludge.  */
       parser->lex_untranslated_string = true;
+      /* Consume the `__attribute__' keyword.  */
       c_parser_consume_token (parser);
+      /* Look for the two `(' tokens.  */
       if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
 	{
 	  parser->lex_untranslated_string = false;
@@ -3993,17 +3995,24 @@  c_parser_attributes (c_parser *parser)
 	  attr_name = c_parser_attribute_any_word (parser);
 	  if (attr_name == NULL)
 	    break;
-	  if (is_cilkplus_vector_p (attr_name))		  
+	  if (is_cilkplus_vector_p (attr_name))
 	    {
 	      c_token *v_token = c_parser_peek_token (parser);
 	      c_parser_cilk_simd_fn_vector_attrs (parser, *v_token);
+	      /* If the next token isn't a comma, we're done.  */
+	      if (!c_parser_next_token_is (parser, CPP_COMMA))
+		break;
 	      continue;
 	    }
 	  c_parser_consume_token (parser);
 	  if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
 	    {
 	      attr = build_tree_list (attr_name, NULL_TREE);
+	      /* Add this attribute to the list.  */
 	      attrs = chainon (attrs, attr);
+	      /* If the next token isn't a comma, we're done.  */
+	      if (!c_parser_next_token_is (parser, CPP_COMMA))
+		break;
 	      continue;
 	    }
 	  c_parser_consume_token (parser);
@@ -4062,8 +4071,13 @@  c_parser_attributes (c_parser *parser)
 					 "expected %<)%>");
 	      return attrs;
 	    }
+	  /* Add this attribute to the list.  */
 	  attrs = chainon (attrs, attr);
+	  /* If the next token isn't a comma, we're done.  */
+	  if (!c_parser_next_token_is (parser, CPP_COMMA))
+	    break;
 	}
+      /* Look for the two `)' tokens.  */
       if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 	c_parser_consume_token (parser);
       else
diff --git gcc/testsuite/gcc.dg/pr67964.c gcc/testsuite/gcc.dg/pr67964.c
index e69de29..095b50f 100644
--- gcc/testsuite/gcc.dg/pr67964.c
+++ gcc/testsuite/gcc.dg/pr67964.c
@@ -0,0 +1,21 @@ 
+/* PR c/67964 */
+/* { dg-do compile } */
+
+extern int fn0 (void) __attribute__ ((const const)); /* { dg-error "expected" } */
+extern int fn1 (void) __attribute__ ((const, const));
+extern int fn2 (void) __attribute__ ((optimize (0) const)); /* { dg-error "expected" } */
+extern int fn3 (void) __attribute__ ((optimize (0), const));
+/* We allow starting/trailing comma.  */
+extern int fn4 (void) __attribute__ ((, const));
+extern int fn5 (void) __attribute__ ((const, ));
+extern int fn6 (void) __attribute__ ((,,,, const,,,,, ));
+extern int fn7 (void) __attribute__ ((,));
+extern int fn8 (void) __attribute__ ((__noreturn__ __noreturn__)); /* { dg-error "expected" } */
+extern int fn9 (void) __attribute__ ((__noreturn__, __noreturn__));
+extern int fn10 (void) __attribute__ ((__cold__ __pure__ __noclone__)); /* { dg-error "expected" } */
+extern int fn11 (void) __attribute__ ((__cold__, __pure__ __noclone__)); /* { dg-error "expected" } */
+int i;
+int ii;
+extern int a __attribute__ ((alias ("i") unused)); /* { dg-error "expected" } */
+extern int a2 __attribute__ ((alias ("i" "i")));
+struct A { char p[6]; } __attribute__((__packed__ packed)); /* { dg-error "expected" } */