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
  • [PATCH] D112659: ... Erich Keane via Phabricator via cfe-commits

Reply via email to