[PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list

Denis Zobnin via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 15 02:45:12 PST 2016


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 at -1{{unexpected '::new' in member initializer list}}
+                        // expected-error at -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 at -1{{unexpected '::new' in member initializer list}}
+                                                                    // expected-error at -2{{unexpected '::delete' in member initializer list}}
+};


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D16216.44971.patch
Type: text/x-patch
Size: 2984 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160115/bf20c54a/attachment.bin>


More information about the cfe-commits mailing list