Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -1520,6 +1520,8 @@ unsigned Kind : 8; }; + enum { NumParamsBits = 16 }; + /// FunctionTypeBitfields store various bits belonging to FunctionProtoType. /// Only common bits are stored here. Additional uncommon bits are stored /// in a trailing object after FunctionProtoType. @@ -1552,7 +1554,7 @@ /// According to [implimits] 8 bits should be enough here but this is /// somewhat easy to exceed with metaprogramming and so we would like to /// keep NumParams as wide as reasonably possible. - unsigned NumParams : 16; + unsigned NumParams : NumParamsBits; /// The type of exception specification this function has. unsigned ExceptionSpecType : 4; @@ -2360,6 +2362,11 @@ /// this type can have nullability because it is dependent. bool canHaveNullability(bool ResultIfUnknown = true) const; + /// @returns The maximum number of parameters for a function. + static constexpr unsigned getMaxNumParams() { + return (1u << NumParamsBits) - 1; + } + /// Retrieve the set of substitutions required when accessing a member /// of the Objective-C receiver type that is declared in the given context. /// Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -326,6 +326,8 @@ def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; +def err_number_of_function_parameters_exceeded : Error< + "number of function parameters 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< Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -6668,6 +6668,15 @@ // If the next token is a comma, consume it and keep reading arguments. } while (TryConsumeToken(tok::comma)); + + // Avoid exceeding the maximum function parameters + // See https://bugs.llvm.org/show_bug.cgi?id=19607 + if (ParamInfo.size() > Type::getMaxNumParams()) { + Diag(ParamInfo[Type::getMaxNumParams() - 1].IdentLoc, + diag::err_number_of_function_parameters_exceeded) + << Type::getMaxNumParams(); + cutOffParsing(); + } } /// [C90] direct-declarator '[' constant-expression[opt] ']' Index: clang/lib/Parse/ParseExprCXX.cpp =================================================================== --- clang/lib/Parse/ParseExprCXX.cpp +++ clang/lib/Parse/ParseExprCXX.cpp @@ -1265,6 +1265,14 @@ ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc); + // If the parameters could not be parsed stop processing. Proceeding is + // not an issue when the maximum scope depth is exceeded. But when the + // maximum number of parameters is exceeded the processing will still hit + // the assertion in FunctionProtoType's constructor. + // See https://bugs.llvm.org/show_bug.cgi?id=19607 + if (Tok.is(tok::eof)) + return ExprError(); + // For a generic lambda, each 'auto' within the parameter declaration // clause creates a template type parameter, so increment the depth. // If we've parsed any explicit template parameters, then the depth will Index: clang/test/Parser/function_parameter_overflow.cpp =================================================================== --- /dev/null +++ clang/test/Parser/function_parameter_overflow.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -fsyntax-only +// RUN: not %clang_cc1 %s -fsyntax-only -DFAIL 2>&1 | FileCheck %s + +#include "parameter_overflow.h" + +void foo(I65535 +#ifdef FAIL +, int +#endif +); +// CHECK: fatal error: number of function parameters exceeded maximum of 65535 Index: clang/test/Parser/lambda_function_parameter_overflow.cpp =================================================================== --- /dev/null +++ clang/test/Parser/lambda_function_parameter_overflow.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -fsyntax-only +// RUN: not %clang_cc1 %s -fsyntax-only -DFAIL 2>&1 | FileCheck %s + +#include "parameter_overflow.h" + +auto foo = [](I65535 +#ifdef FAIL +, int +#endif +){}; +// CHECK: fatal error: number of function parameters exceeded maximum of 65535 Index: clang/test/Parser/parameter_overflow.h =================================================================== --- /dev/null +++ clang/test/Parser/parameter_overflow.h @@ -0,0 +1,9 @@ +#pragma once + +#define I10 int, int, int, int, int, int, int, int, int, int +#define I50 I10, I10, I10, I10, I10 +#define I500 I50, I50, I50, I50, I50, I50, I50, I50, I50, I50 +#define I5000 I500, I500, I500, I500, I500, I500, I500, I500, I500, I500 +#define I60000 I5000, I5000, I5000, I5000, I5000, I5000, I5000, I5000, I5000, I5000, I5000, I5000 + +#define I65535 I60000, I5000, I500, I10, I10, I10, int, int, int, int, int