Skip to content

Commit

Permalink
Check for resource exhaustion when recursively parsing declarators
Browse files Browse the repository at this point in the history
With sufficiently tortured code, it's possible to cause a stack
overflow when parsing declarators. Thus, we now check for resource
exhaustion when recursively parsing declarators so that we can at least
warn the user we're about to crash before we actually crash.

Fixes #51642

Differential Revision: https://reviews.llvm.org/D124915
  • Loading branch information
AaronBallman committed May 12, 2022
1 parent 6089fd6 commit c671041
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
4 changes: 3 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ Improvements to Clang's diagnostics
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
-------------------------------------------------
Expand Down
15 changes: 10 additions & 5 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5765,11 +5765,12 @@ void Parser::ParseTypeQualifierListOpt(
}

/// 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);
Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {
ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
});
}

static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
Expand Down Expand Up @@ -5880,7 +5881,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
D.ExtendWithDeclSpec(DS);

// Recurse to parse whatever is left.
ParseDeclaratorInternal(D, DirectDeclParser);
Actions.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.
Expand Down Expand Up @@ -5929,7 +5932,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
D.ExtendWithDeclSpec(DS);

// Recursively parse the declarator.
ParseDeclaratorInternal(D, DirectDeclParser);
Actions.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(
Expand Down Expand Up @@ -5974,7 +5978,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
}

// Recursively parse the declarator.
ParseDeclaratorInternal(D, DirectDeclParser);
Actions.runWithSufficientStackSpace(
D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });

if (D.getNumTypeObjects() > 0) {
// C++ [dcl.ref]p4: There shall be no references to references.
Expand Down

0 comments on commit c671041

Please sign in to comment.