Skip to content

Commit 3315f0a

Browse files
[Serialization] Check for stack exhaustion when reading declarations (#79875)
Particular example that lead to this is a very long chain of `UsingShadowDecl`s that we hit in our codebase in generated code. To avoid that, check for stack exhaustion when deserializing the declaration. At that point, we can point to source location of a particular declaration that is being deserialized.
1 parent b41dbe6 commit 3315f0a

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

clang/include/clang/Serialization/ASTReader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ class ASTReader
429429
FileManager &FileMgr;
430430
const PCHContainerReader &PCHContainerRdr;
431431
DiagnosticsEngine &Diags;
432+
// Sema has duplicate logic, but SemaObj can sometimes be null so ASTReader
433+
// has its own version.
434+
bool WarnedStackExhausted = false;
432435

433436
/// The semantic analysis object that will be processing the
434437
/// AST files and the translation unit that uses it.
@@ -2135,6 +2138,8 @@ class ASTReader
21352138
/// Report a diagnostic.
21362139
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const;
21372140

2141+
void warnStackExhausted(SourceLocation Loc);
2142+
21382143
IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID);
21392144

21402145
IdentifierInfo *readIdentifier(ModuleFile &M, const RecordData &Record,

clang/lib/Serialization/ASTReader.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "clang/Basic/CommentOptions.h"
4545
#include "clang/Basic/Diagnostic.h"
4646
#include "clang/Basic/DiagnosticError.h"
47+
#include "clang/Basic/DiagnosticIDs.h"
4748
#include "clang/Basic/DiagnosticOptions.h"
4849
#include "clang/Basic/DiagnosticSema.h"
4950
#include "clang/Basic/ExceptionSpecificationType.h"
@@ -9404,6 +9405,20 @@ DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) const {
94049405
return Diags.Report(Loc, DiagID);
94059406
}
94069407

9408+
void ASTReader::warnStackExhausted(SourceLocation Loc) {
9409+
// When Sema is available, avoid duplicate errors.
9410+
if (SemaObj) {
9411+
SemaObj->warnStackExhausted(Loc);
9412+
return;
9413+
}
9414+
9415+
if (WarnedStackExhausted)
9416+
return;
9417+
WarnedStackExhausted = true;
9418+
9419+
Diag(Loc, diag::warn_stack_exhausted);
9420+
}
9421+
94079422
/// Retrieve the identifier table associated with the
94089423
/// preprocessor.
94099424
IdentifierTable &ASTReader::getIdentifierTable() {

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "clang/Basic/PragmaKinds.h"
5050
#include "clang/Basic/SourceLocation.h"
5151
#include "clang/Basic/Specifiers.h"
52+
#include "clang/Basic/Stack.h"
5253
#include "clang/Sema/IdentifierResolver.h"
5354
#include "clang/Serialization/ASTBitCodes.h"
5455
#include "clang/Serialization/ASTRecordReader.h"
@@ -4127,7 +4128,10 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
41274128
// calls to Decl::getASTContext() by Decl's methods will find the
41284129
// TranslationUnitDecl without crashing.
41294130
D->setDeclContext(Context.getTranslationUnitDecl());
4130-
Reader.Visit(D);
4131+
4132+
// Reading some declarations can result in deep recursion.
4133+
clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); },
4134+
[&] { Reader.Visit(D); });
41314135

41324136
// If this declaration is also a declaration context, get the
41334137
// offsets for its tables of lexical and visible declarations.

0 commit comments

Comments
 (0)