d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: kcc, rsmith.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Fix for a case found by fuzzing PR23057 (comment #33 
https://llvm.org/bugs/show_bug.cgi?id=23057#c33). Diagnose and consume 
unexpected ::new and ::delete tokens to prevent infinite loop in parsing a 
member initializer list.

http://reviews.llvm.org/D16216

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseDeclCXX.cpp
  test/Parser/cxx-invalid-function-decl.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3237,6 +3237,20 @@
   CXXScopeSpec SS;
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   ParsedType TemplateTypeTy;
+  // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left
+  // them untouched. Diagnose it now to prevent infinite loop on parsing such
+  // code: "f() : ::new".
+  if (Tok.is(tok::coloncolon)) {
+    tok::TokenKind NextKind = NextToken().getKind();
+    if (NextKind == tok::kw_new || NextKind == tok::kw_delete) {
+      SourceRange Range(Tok.getLocation(), NextToken().getEndLoc());
+      Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist)
+          << (NextKind == tok::kw_delete) << Range;
+      ConsumeToken(); // the '::' token.
+      ConsumeToken(); // 'new' or 'delete'.
+      return true;
+    }
+  }
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
     if (TemplateId->Kind == TNK_Type_template ||
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -161,6 +161,8 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_unexpected_semi : Error<"unexpected ';' before %0">;
+def err_unexpected_in_member_initlist : Error<
+  "unexpected %select{'::new'|'::delete'}0 in member initializer list">;
 
 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
Index: test/Parser/cxx-invalid-function-decl.cpp
===================================================================
--- test/Parser/cxx-invalid-function-decl.cpp
+++ test/Parser/cxx-invalid-function-decl.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f() : X() ::new{}; // expected-error{{missing ',' between base or member 
initializers}}
+                        // expected-error@-1{{unexpected '::new' in member 
initializer list}}
+                        // expected-error@-2{{only constructors take base 
initializers}}
+
+template <class T>
+struct Base1 {
+  T x1;
+  Base1(T a1) : x1(a1) {}
+};
+
+template <class T>
+struct Base2 {
+  T x2;
+  Base2(T a2) : x2(a2) {}
+};
+
+struct S : public Base1<int>, public Base2<float> {
+  int x;
+  S() : ::Base1<int>(0) ::new, ::Base2<float>(1.0) ::delete x(2) {} // 
expected-error3{{missing ',' between base or member initializers}}
+                                                                    // 
expected-error@-1{{unexpected '::new' in member initializer list}}
+                                                                    // 
expected-error@-2{{unexpected '::delete' in member initializer list}}
+};


Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3237,6 +3237,20 @@
   CXXScopeSpec SS;
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   ParsedType TemplateTypeTy;
+  // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left
+  // them untouched. Diagnose it now to prevent infinite loop on parsing such
+  // code: "f() : ::new".
+  if (Tok.is(tok::coloncolon)) {
+    tok::TokenKind NextKind = NextToken().getKind();
+    if (NextKind == tok::kw_new || NextKind == tok::kw_delete) {
+      SourceRange Range(Tok.getLocation(), NextToken().getEndLoc());
+      Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist)
+          << (NextKind == tok::kw_delete) << Range;
+      ConsumeToken(); // the '::' token.
+      ConsumeToken(); // 'new' or 'delete'.
+      return true;
+    }
+  }
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
     if (TemplateId->Kind == TNK_Type_template ||
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -161,6 +161,8 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_unexpected_semi : Error<"unexpected ';' before %0">;
+def err_unexpected_in_member_initlist : Error<
+  "unexpected %select{'::new'|'::delete'}0 in member initializer list">;
 
 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
Index: test/Parser/cxx-invalid-function-decl.cpp
===================================================================
--- test/Parser/cxx-invalid-function-decl.cpp
+++ test/Parser/cxx-invalid-function-decl.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f() : X() ::new{}; // expected-error{{missing ',' between base or member initializers}}
+                        // expected-error@-1{{unexpected '::new' in member initializer list}}
+                        // expected-error@-2{{only constructors take base initializers}}
+
+template <class T>
+struct Base1 {
+  T x1;
+  Base1(T a1) : x1(a1) {}
+};
+
+template <class T>
+struct Base2 {
+  T x2;
+  Base2(T a2) : x2(a2) {}
+};
+
+struct S : public Base1<int>, public Base2<float> {
+  int x;
+  S() : ::Base1<int>(0) ::new, ::Base2<float>(1.0) ::delete x(2) {} // expected-error3{{missing ',' between base or member initializers}}
+                                                                    // expected-error@-1{{unexpected '::new' in member initializer list}}
+                                                                    // expected-error@-2{{unexpected '::delete' in member initializer list}}
+};
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to