[clang] c978f0f - [clang] Fix segmentation fault caused by stack overflow on deeply nested expressions (#111701)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 14 05:06:54 PDT 2024
Author: Boaz Brickner
Date: 2024-10-14T14:06:50+02:00
New Revision: c978f0f7ac33a5085053da7189201babd366c82d
URL: https://github.com/llvm/llvm-project/commit/c978f0f7ac33a5085053da7189201babd366c82d
DIFF: https://github.com/llvm/llvm-project/commit/c978f0f7ac33a5085053da7189201babd366c82d.diff
LOG: [clang] Fix segmentation fault caused by stack overflow on deeply nested expressions (#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: #111699
Added:
Modified:
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index ec54da0a5b2571..1e8ffb53b53a09 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1528,7 +1528,12 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
///
LValue CodeGenFunction::EmitLValue(const Expr *E,
KnownNonNull_t IsKnownNonNull) {
- LValue LV = EmitLValueHelper(E, IsKnownNonNull);
+ // Running with sufficient stack space to avoid deeply nested expressions
+ // cause a stack overflow.
+ LValue LV;
+ CGM.runWithSufficientStackSpace(
+ E->getExprLoc(), [&] { LV = EmitLValueHelper(E, IsKnownNonNull); });
+
if (IsKnownNonNull && !LV.isKnownNonNull())
LV.setKnownNonNull();
return LV;
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7f0e0de61e477b..b05ab3606a698b 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -44,6 +44,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/BackendUtil.h"
@@ -1593,6 +1594,19 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
}
+void CodeGenModule::warnStackExhausted(SourceLocation Loc) {
+ // Only warn about this once.
+ if (!WarnedStackExhausted) {
+ getDiags().Report(Loc, diag::warn_stack_exhausted);
+ WarnedStackExhausted = true;
+ }
+}
+
+void CodeGenModule::runWithSufficientStackSpace(SourceLocation Loc,
+ llvm::function_ref<void()> Fn) {
+ clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
+}
+
llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
return llvm::ConstantInt::get(SizeTy, size.getQuantity());
}
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index c58bb88035ca8a..57e06cbfac13a9 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -336,6 +336,7 @@ class CodeGenModule : public CodeGenTypeCache {
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
InstrProfStats PGOStats;
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
+ bool WarnedStackExhausted = false;
// A set of references that have only been seen via a weakref so far. This is
// used to remove the weak of the reference if we ever see a direct reference
@@ -1297,6 +1298,16 @@ class CodeGenModule : public CodeGenTypeCache {
/// Print out an error that codegen doesn't support the specified decl yet.
void ErrorUnsupported(const Decl *D, const char *Type);
+ /// 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 to avoid stack
+ /// overflow.
+ void runWithSufficientStackSpace(SourceLocation Loc,
+ llvm::function_ref<void()> Fn);
+
/// Set the attributes on the LLVM function for the given decl and function
/// info. This applies attributes necessary for handling the ABI as well as
/// user specified attributes like section.
More information about the cfe-commits
mailing list