Limit Subzero routine stack size to 512 KiB

Fuzzing tests generate shaders with large arrays or very high numbers of local variables, which can cause stack overflow. We need to limit the allowable stack memory usage of generated routines. Note this change does not yet gracefully deal with routines which exceed this limit. They will cause a null pointer dereference instead of a stack overflow. The default stack size limit of 1 MiB at the Subzero level is to ensure we catch cases of excessive stack sizes even in the case no explicit limit was set. At the Reactor level we reduce it to 512 KiB to prevent actual stack overflow for a 1 MiB stack, assuming some earlier calls might want to use the stack. Also, our legacy 'ASM' compiler for GLSL allocates 4096 'registers' of 4 components for 128-bit SIMD, which already requires 256 KiB. Bug: b/157555596 Change-Id: I474285eecc786496edffbaef29719ca0cdf03f7d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52329 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Commit-Queue: Nicolas Capens <nicolascapens@google.com>
parent 25f0f858
......@@ -64,7 +64,9 @@ namespace sz {
Ice::Cfg *createFunction(Ice::GlobalContext *context, Ice::Type returnType, const std::vector<Ice::Type> &paramTypes)
{
uint32_t sequenceNumber = 0;
auto function = Ice::Cfg::create(context, sequenceNumber).release();
auto *function = Ice::Cfg::create(context, sequenceNumber).release();
function->setStackSizeLimit(512 * 1024); // 512 KiB
Ice::CfgLocalAllocatorScope allocScope{ function };
......@@ -1039,6 +1041,11 @@ static std::shared_ptr<Routine> acquireRoutine(Ice::Cfg *const (&functions)[Coun
}
currFunc->emitIAS();
if(currFunc->hasError())
{
return nullptr;
}
}
// Emit items
......
......@@ -274,6 +274,9 @@ public:
/// in the correct information once everything is known.
void fixPhiNodes();
void setStackSizeLimit(uint32_t Limit) { StackSizeLimit = Limit; }
uint32_t getStackSizeLimit() const { return StackSizeLimit; }
private:
friend class CfgAllocatorTraits; // for Allocator access.
......@@ -344,6 +347,7 @@ private:
/// should be called to avoid spurious validation failures.
const CfgNode *CurrentNode = nullptr;
CfgVector<Loop> LoopInfo;
uint32_t StackSizeLimit = 1 * 1024 * 1024; // 1 MiB
public:
static void TlsInit() { CfgAllocatorTraits::init(); }
......
......@@ -1202,6 +1202,11 @@ void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) {
SpillAreaSizeBytes = StackSize - StackOffset; // Adjust for alignment, if any
if (SpillAreaSizeBytes) {
auto *Func = Node->getCfg();
if (SpillAreaSizeBytes > Func->getStackSizeLimit()) {
Func->setError("Stack size limit exceeded");
}
emitStackProbe(SpillAreaSizeBytes);
// Generate "sub stackptr, SpillAreaSizeBytes"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment