Skip to content

Commit f6022e1

Browse files
bricknerbDanielCChen
authored andcommitted
[clang] Fix segmentation fault caused by stack overflow on deeply nested expressions (llvm#111701)
Done by calling clang::runWithSufficientStackSpace(). Added CodeGenModule::runWithSufficientStackSpace() method similar to the one in Sema to provide a single warning when this triggers Fixes: llvm#111699
1 parent 8989182 commit f6022e1

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,12 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
15281528
///
15291529
LValue CodeGenFunction::EmitLValue(const Expr *E,
15301530
KnownNonNull_t IsKnownNonNull) {
1531-
LValue LV = EmitLValueHelper(E, IsKnownNonNull);
1531+
// Running with sufficient stack space to avoid deeply nested expressions
1532+
// cause a stack overflow.
1533+
LValue LV;
1534+
CGM.runWithSufficientStackSpace(
1535+
E->getExprLoc(), [&] { LV = EmitLValueHelper(E, IsKnownNonNull); });
1536+
15321537
if (IsKnownNonNull && !LV.isKnownNonNull())
15331538
LV.setKnownNonNull();
15341539
return LV;

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "clang/Basic/FileManager.h"
4545
#include "clang/Basic/Module.h"
4646
#include "clang/Basic/SourceManager.h"
47+
#include "clang/Basic/Stack.h"
4748
#include "clang/Basic/TargetInfo.h"
4849
#include "clang/Basic/Version.h"
4950
#include "clang/CodeGen/BackendUtil.h"
@@ -1593,6 +1594,19 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
15931594
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
15941595
}
15951596

1597+
void CodeGenModule::warnStackExhausted(SourceLocation Loc) {
1598+
// Only warn about this once.
1599+
if (!WarnedStackExhausted) {
1600+
getDiags().Report(Loc, diag::warn_stack_exhausted);
1601+
WarnedStackExhausted = true;
1602+
}
1603+
}
1604+
1605+
void CodeGenModule::runWithSufficientStackSpace(SourceLocation Loc,
1606+
llvm::function_ref<void()> Fn) {
1607+
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
1608+
}
1609+
15961610
llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
15971611
return llvm::ConstantInt::get(SizeTy, size.getQuantity());
15981612
}

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ class CodeGenModule : public CodeGenTypeCache {
336336
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
337337
InstrProfStats PGOStats;
338338
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
339+
bool WarnedStackExhausted = false;
339340

340341
// A set of references that have only been seen via a weakref so far. This is
341342
// used to remove the weak of the reference if we ever see a direct reference
@@ -1297,6 +1298,16 @@ class CodeGenModule : public CodeGenTypeCache {
12971298
/// Print out an error that codegen doesn't support the specified decl yet.
12981299
void ErrorUnsupported(const Decl *D, const char *Type);
12991300

1301+
/// Warn that the stack is nearly exhausted.
1302+
void warnStackExhausted(SourceLocation Loc);
1303+
1304+
/// Run some code with "sufficient" stack space. (Currently, at least 256K is
1305+
/// guaranteed). Produces a warning if we're low on stack space and allocates
1306+
/// more in that case. Use this in code that may recurse deeply to avoid stack
1307+
/// overflow.
1308+
void runWithSufficientStackSpace(SourceLocation Loc,
1309+
llvm::function_ref<void()> Fn);
1310+
13001311
/// Set the attributes on the LLVM function for the given decl and function
13011312
/// info. This applies attributes necessary for handling the ABI as well as
13021313
/// user specified attributes like section.

0 commit comments

Comments
 (0)