erichkeane created this revision. erichkeane added reviewers: aaron.ballman, majnemer, EricWF. Herald added subscribers: dexonsmith, dang. erichkeane requested review of this revision.
As brought up in PR48246, passing a large value to `__make_integer_seq` results in the compiler getting stuck in a large loop and potentially crashing if it runs out of memory as a result. This patch puts a command-line configurable limit in place to limit the size to something reasonable. I chose 2^24 as default after a brief experimentation with the debug compiler, which made it take a few minutes. On a release build, a program with a 2^24 value takes roughly 30 seconds, and uses about 3.3GB of ram. https://reviews.llvm.org/D112659 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/SemaCXX/make_integer_seq.cpp
Index: clang/test/SemaCXX/make_integer_seq.cpp =================================================================== --- clang/test/SemaCXX/make_integer_seq.cpp +++ clang/test/SemaCXX/make_integer_seq.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,smalllimit -fint-seq-limit 500 -std=c++11 %s static_assert(__has_builtin(__make_integer_seq), ""); @@ -51,3 +52,18 @@ __make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-error{{different template parameters}} // expected-note@make_integer_seq.cpp:* {{template parameter has a different kind}} // expected-note@make_integer_seq.cpp:* {{previous template template parameter is here}} + +__make_integer_seq<Seq, int, 1200> PR48246; +// smalllimit-error@-1{{'__make_integer_seq' exceeded maximum limit of 500}} +// smalllimit-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}} + +// Default value is ~16.7 million, so without the command line option, fail. +__make_integer_seq<Seq, int, 16800000> PR48246_b; +// expected-error@-1{{'__make_integer_seq' exceeded maximum limit of}} +// expected-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}} + +using size_t = unsigned long long; + +__make_integer_seq<Seq, size_t, ((size_t)1) - 2> PR48246_c; +// expected-error@-1{{'__make_integer_seq' exceeded maximum limit of}} +// expected-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}} Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -3452,6 +3452,18 @@ return QualType(); } + // The below loop ends up taking a very long time and causing an OOM crash + // if 'N' is too large. Limit to a command-line specified value. + if (NumArgs > SemaRef.getLangOpts().MakeIntSeqSize) { + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::err_integer_sequence_length_exceeded) + << SemaRef.getLangOpts().MakeIntSeqSize; + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::note_integer_sequence_length_exceeded) + << SemaRef.getLangOpts().MakeIntSeqSize; + return QualType(); + } + QualType ArgTy = NumArgsArg.getIntegralType(); TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument gets reused as the first template argument in the Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5617,6 +5617,11 @@ CmdArgs.push_back(A->getValue()); } + if (Arg *A = Args.getLastArg(options::OPT_fint_seq_limit_EQ)) { + CmdArgs.push_back("-fint-seq-limit"); + CmdArgs.push_back(A->getValue()); + } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { CmdArgs.push_back("-fconstexpr-depth"); CmdArgs.push_back(A->getValue()); Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2626,6 +2626,7 @@ Group<f_Group>; def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, Group<f_Group>; +def fint_seq_limit_EQ : Joined<["-"], "fint-seq-limit=">, Group<f_Group>; def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">, Group<f_Group>, HelpText<"Generate a YAML optimization record file">; @@ -5679,6 +5680,9 @@ def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">, HelpText<"Maximum number of 'operator->'s to call for a member access">, MarshallingInfoInt<LangOpts<"ArrowDepth">, "256">; +def fint_seq_limit : Separate<["-"], "fint-seq-limit">, + HelpText<"Maximum value of the __make_integer_seq builtin">, + MarshallingInfoInt<LangOpts<"MakeIntSeqSize">, "16777216">; def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">, HelpText<"Maximum depth of recursive constexpr function calls">, MarshallingInfoInt<LangOpts<"ConstexprCallDepth">, "512">; Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -362,6 +362,8 @@ "maximum constexpr call depth") BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576, "maximum constexpr evaluation steps") +BENIGN_LANGOPT(MakeIntSeqSize, 32, 16777216, + "maximum value for __make_integer_seq") BENIGN_LANGOPT(EnableNewConstInterp, 1, 0, "enable the experimental new constant interpreter") BENIGN_LANGOPT(BracketDepth, 32, 256, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5092,6 +5092,11 @@ DefaultFatal, NoSFINAE; def note_template_recursion_depth : Note< "use -ftemplate-depth=N to increase recursive template instantiation depth">; +def err_integer_sequence_length_exceeded + : Error<"'__make_integer_seq' exceeded maximum limit of %0">; +def note_integer_sequence_length_exceeded + : Note<"use -fint-seq-limit=N to increase '__make_integer_seq' " + "limit">; def err_template_instantiate_within_definition : Error< "%select{implicit|explicit}0 instantiation of template %1 within its"
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits