From b9be5ce8f3e0e697a61ad16e2c669de6ea8f8739 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 9 Nov 2019 15:32:35 +0100 Subject: [PATCH] [Parser] Warn when ScopeDepthOrObjCQuals overflows Before when the overflow occured an assertion was triggered. Now check whether the maximum has been reached and warn properly. This patch fixes the original submission of PR19607. Differential Revision: https://reviews.llvm.org/D63975 --- clang/include/clang/AST/Decl.h | 8 +++- clang/include/clang/Basic/DiagnosticParseKinds.td | 2 + clang/lib/Parse/ParseDecl.cpp | 13 +++++ clang/test/Parser/nested_blocks_overflow.cpp | 54 +++++++++++++++++++++ .../Parser/nested_function_prototype_overflow.cpp | 9 ++++ clang/test/Parser/nested_lambda_overflow.cpp | 55 ++++++++++++++++++++++ 6 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 clang/test/Parser/nested_blocks_overflow.cpp create mode 100644 clang/test/Parser/nested_function_prototype_overflow.cpp create mode 100644 clang/test/Parser/nested_lambda_overflow.cpp diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 16094c0..31adfc5 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -921,11 +921,13 @@ protected: /// 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 @@ public: 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 index 7c9f4da..dc9f677 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -325,6 +325,8 @@ def err_for_range_expected_decl : Error< 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 index c41eb74..e5c17a3 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6566,6 +6566,19 @@ void Parser::ParseParameterDeclarationClause( 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 index 0000000..e8366a8 --- /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 index 0000000..29b382d --- /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 index 0000000..afaa9dc --- /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 -- 2.7.4