diff options
author | Boaz Brickner <brickner@google.com> | 2024-10-14 14:06:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-14 14:06:50 +0200 |
commit | c978f0f7ac33a5085053da7189201babd366c82d (patch) | |
tree | 15f651a370f74ee62cea1dc32d6c1c58c1464d82 /clang/lib/CodeGen | |
parent | 6a98c4a1602591c942f01dceb3aa29ffd4cf1e5b (diff) | |
download | llvm-c978f0f7ac33a5085053da7189201babd366c82d.zip llvm-c978f0f7ac33a5085053da7189201babd366c82d.tar.gz llvm-c978f0f7ac33a5085053da7189201babd366c82d.tar.bz2 |
[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
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 11 |
3 files changed, 31 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ec54da0..1e8ffb5 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 7f0e0de..b05ab36 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 c58bb88..57e06cb 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -336,6 +336,7 @@ private: 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 @@ public: /// 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. |