aaron.ballman updated this revision to Diff 428969. aaron.ballman added a comment.
Rebased. I removed the test coverage because it turned out to not be testing anything. If we exhaust resources, then we don't run the `-verify` to test the diagnostic behavior, and we're relying on the crash being the test condition, but any crash will suffice. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124915/new/ https://reviews.llvm.org/D124915 Files: clang/docs/ReleaseNotes.rst clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp
Index: clang/lib/Parse/Parser.cpp =================================================================== --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/Stack.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" @@ -2612,6 +2613,19 @@ return false; } +void Parser::warnStackExhausted(SourceLocation Loc) { + // Only warn about this once. + if (!Actions.WarnedStackExhausted) { + Diag(Loc, diag::warn_stack_exhausted); + Actions.WarnedStackExhausted = true; + } +} + +void Parser::runWithSufficientStackSpace(SourceLocation Loc, + llvm::function_ref<void()> Fn) { + clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn); +} + bool BalancedDelimiterTracker::diagnoseOverflow() { P.Diag(P.Tok, diag::err_bracket_depth_exceeded) << P.getLangOpts().BracketDepth; Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -5765,11 +5765,12 @@ } /// ParseDeclarator - Parse and verify a newly-initialized declarator. -/// void Parser::ParseDeclarator(Declarator &D) { /// This implements the 'declarator' production in the C grammar, then checks /// for well-formedness and issues diagnostics. - ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + }); } static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, @@ -5880,7 +5881,9 @@ D.ExtendWithDeclSpec(DS); // Recurse to parse whatever is left. - ParseDeclaratorInternal(D, DirectDeclParser); + runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, DirectDeclParser); + }); // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. @@ -5929,7 +5932,8 @@ D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. - ParseDeclaratorInternal(D, DirectDeclParser); + runWithSufficientStackSpace( + D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer( @@ -5974,7 +5978,8 @@ } // Recursively parse the declarator. - ParseDeclaratorInternal(D, DirectDeclParser); + runWithSufficientStackSpace( + D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); if (D.getNumTypeObjects() > 0) { // C++ [dcl.ref]p4: There shall be no references to references. Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -793,6 +793,16 @@ return PP.LookAhead(N-1); } + /// Warn that the stack is nearly exhausted. + void warnStackExhausted(SourceLocation Loc); + + /// Run some code with "sufficient" stack space. (Currently, at least 256K is + /// guaranteed). Produces a warning if we're low on stack space and allocates + /// more in that case. Use this in code that may recurse deeply (for example, + /// in template instantiation) to avoid stack overflow. + void runWithSufficientStackSpace(SourceLocation Loc, + llvm::function_ref<void()> Fn); + public: /// NextToken - This peeks ahead one token and returns it without /// consuming it. Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -222,7 +222,9 @@ on such language mode, ``-Wpre-c2x-compat`` and ``-Wpre-c++2b-compat`` diagnostic flags report a compatibility issue. Fixes `Issue 55306 <https://github.com/llvm/llvm-project/issues/55306>`_. - +- Clang now checks for stack resource exhaustion when recursively parsing + declarators in order to give a diagnostic before we run out of stack space. + This fixes `Issue 51642 <https://github.com/llvm/llvm-project/issues/51642>`_. Non-comprehensive list of changes in this release -------------------------------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits