r224915 - Don't crash on malformed attributes in an incorrect location.

Nico Weber nicolasweber at gmx.de
Sun Dec 28 22:56:50 PST 2014


Author: nico
Date: Mon Dec 29 00:56:50 2014
New Revision: 224915

URL: http://llvm.org/viewvc/llvm-project?rev=224915&view=rev
Log:
Don't crash on malformed attributes in an incorrect location.

r168626 added nicer diagnostics for attributes in the wrong places, such as
after the `final` on a class.  To do this, it added code that did high-level
pattern matching for e.g. 'final' 'alignas' '(' and then skipped until the
closing ')'.  If it saw that, it then went down the regular class parsing
path and then called MaybeParseCXX11Attributes() to parse the attribute after
the 'final' using real attribute parsing code.  On invalid attributes, the
real attribute parsing code could eat more tokens than the pattern matching
code and for example skip past the '{' starting the class, which would then
lead to an assert.  To prevent this, check for a good state after calling
MaybeParseCXX11Attributes() (which morphed into CheckMisplacedCXX11Attribute()
in r175575) and bail out if things look bleak.

Found by SLi's afl bot.

Modified:
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/test/Parser/cxx0x-attributes.cpp

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=224915&r1=224914&r2=224915&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Dec 29 00:56:50 2014
@@ -2706,6 +2706,16 @@ void Parser::ParseCXXMemberSpecification
     // and the only possible place for them to appertain
     // to the class would be between class-key and class-name.
     CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
+
+    // ParseClassSpecifier() does only a superficial check for attributes before
+    // deciding to call this method.  For example, for
+    // `class C final alignas ([l) {` it will decide that this looks like a
+    // misplaced attribute since it sees `alignas '(' ')'`.  But the actual
+    // attribute parsing code will try to parse the '[' as a constexpr lambda
+    // and consume enough tokens that the alignas parsing code will eat the
+    // opening '{'.  So bail out if the next token isn't one we expect.
+    if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace))
+      return;
   }
 
   if (Tok.is(tok::colon)) {

Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=224915&r1=224914&r2=224915&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Mon Dec 29 00:56:50 2014
@@ -330,3 +330,7 @@ namespace {
   [[deprecated()]] void foo(); // expected-error {{parentheses must be omitted if 'deprecated' attribute's argument list is empty}}
   [[gnu::deprecated()]] void quux();
 }
+
+// The diagnostics here don't matter much, this just shouldn't crash:
+class C final [[deprecated(l]] {}; // expected-error {{use of undeclared identifier}} expected-error {{expected ']'}} expected-error {{an attribute list cannot appear here}}
+class C final alignas ([l) {}; // expected-error {{expected ';' after class}}





More information about the cfe-commits mailing list