diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -921,11 +921,13 @@ /// Whether this parameter is an ObjC method parameter or not. unsigned IsObjCMethodParam : 1; + enum { NumScopeDepthOrObjCQualsBits = 7 }; + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was /// declared. - unsigned ScopeDepthOrObjCQuals : 7; + unsigned ScopeDepthOrObjCQuals : NumScopeDepthOrObjCQualsBits; /// The number of parameters preceding this parameter in the /// function parameter scope in which it was declared. @@ -1650,6 +1652,10 @@ return ParmVarDeclBits.ScopeDepthOrObjCQuals; } + static constexpr unsigned getMaxFunctionScopeDepth() { + return (1u << ParmVarDeclBitfields::NumScopeDepthOrObjCQualsBits) - 1; + } + /// Returns the index of this parameter in its prototype or method scope. unsigned getFunctionScopeIndex() const { return getParameterIndex(); diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -325,6 +325,8 @@ def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; +def err_function_scope_depth_exceeded : Error< + "function scope depth exceeded maximum of %0">, DefaultFatal; def err_missing_comma_before_ellipsis : Error< "C requires a comma prior to the ellipsis in a variadic function type">; def err_unexpected_typedef_ident : Error< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6566,6 +6566,19 @@ ParsedAttributes &FirstArgAttrs, SmallVectorImpl &ParamInfo, SourceLocation &EllipsisLoc) { + + // Avoid exceeding the maximum function scope depth. + // See https://bugs.llvm.org/show_bug.cgi?id=19607 + // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with + // getFunctionPrototypeDepth() - 1. + if (getCurScope()->getFunctionPrototypeDepth() - 1 > + ParmVarDecl::getMaxFunctionScopeDepth()) { + Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded) + << ParmVarDecl::getMaxFunctionScopeDepth(); + cutOffParsing(); + return; + } + do { // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq // before deciding this was a parameter-declaration-clause. diff --git a/clang/test/Parser/nested_blocks_overflow.cpp b/clang/test/Parser/nested_blocks_overflow.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Parser/nested_blocks_overflow.cpp @@ -0,0 +1,54 @@ +// RUN: %clang %s -fsyntax-only -fblocks -fbracket-depth=512 +// RUN: not %clang %s -fsyntax-only -fblocks -fbracket-depth=512 -DFAIL 2>&1 | FileCheck %s + +template int foo(T &&t); + +void bar(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( + +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( + +#ifdef FAIL +^(int x = foo( +#endif + +^(int x = foo(1)){} + +#ifdef FAIL +)){} +#endif + +)){})){})){})){})){})){} + +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)); + +// CHECK: fatal error: function scope depth exceeded maximum of 127 diff --git a/clang/test/Parser/nested_function_prototype_overflow.cpp b/clang/test/Parser/nested_function_prototype_overflow.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Parser/nested_function_prototype_overflow.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only +// RUN: not %clang_cc1 %s -fsyntax-only -DFAIL 2>&1 | FileCheck %s + +void foo(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)( +#ifdef FAIL +void (*f)() +#endif +))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); +// CHECK: fatal error: function scope depth exceeded maximum of 127 diff --git a/clang/test/Parser/nested_lambda_overflow.cpp b/clang/test/Parser/nested_lambda_overflow.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Parser/nested_lambda_overflow.cpp @@ -0,0 +1,55 @@ +// RUN: %clang %s -fsyntax-only -fbracket-depth=512 +// RUN: not %clang %s -fsyntax-only -fbracket-depth=512 -DFAIL 2>&1 | FileCheck %s + +template int foo(T &&t); + +void bar(int x = foo( + +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( + +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( + +#ifdef FAIL +[](int x = foo( +#endif + +[](int x = foo(1)){} + +#ifdef FAIL +)){} +#endif + +)){})){})){})){})){})){} + +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)); + +// CHECK: fatal error: function scope depth exceeded maximum of 127