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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits