Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 031a767

Browse files
johnstiles-googleSkia Commit-Bot
authored andcommitted
Stop the inliner after it has inlined 2500 statements in a program.
This prevents OOMing when given a pathological input, but is large enough that almost all inputs should continue to compile as-is. Change-Id: If5c46711b886ee08495bfd09af537e9dc7ea5649 Bug: skia:10945, oss-fuzz:27442 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/334838 Commit-Queue: John Stiles <[email protected]> Reviewed-by: Brian Osman <[email protected]> Auto-Submit: John Stiles <[email protected]>
1 parent 4757a60 commit 031a767

File tree

7 files changed

+2177
-362
lines changed

7 files changed

+2177
-362
lines changed

gn/sksl_tests.gni

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ sksl_shared_tests = [
257257
sksl_inliner_tests = [
258258
"$_tests/sksl/inliner/DoWhileBodyMustBeInlinedIntoAScope.sksl",
259259
"$_tests/sksl/inliner/DoWhileTestCannotBeInlined.sksl",
260-
"$_tests/sksl/inliner/ExponentialGrowth.sksl",
261260
"$_tests/sksl/inliner/ForBodyMustBeInlinedIntoAScope.sksl",
262261
"$_tests/sksl/inliner/ForInitializerExpressionsCanBeInlined.sksl",
263262
"$_tests/sksl/inliner/ForWithReturnInsideCannotBeInlined.sksl",
@@ -323,6 +322,7 @@ sksl_blend_tests = [
323322

324323
sksl_settings_tests = [
325324
"$_tests/sksl/glsl/TypePrecision.sksl",
325+
"$_tests/sksl/inliner/ExponentialGrowth.sksl",
326326
"$_tests/sksl/inliner/InlinerCanBeDisabled.sksl",
327327
"$_tests/sksl/inliner/InlinerWrapsEarlyReturnsWithDoWhileBlock.sksl",
328328
"$_tests/sksl/shared/CrossIntrinsic.sksl",

src/sksl/SkSLInliner.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
namespace SkSL {
5757
namespace {
5858

59+
static constexpr int kInlinedStatementLimit = 2500;
60+
5961
static bool contains_returns_above_limit(const FunctionDefinition& funcDef, int limit) {
6062
class CountReturnsWithLimit : public ProgramVisitor {
6163
public:
@@ -310,6 +312,7 @@ void Inliner::reset(const Context* context, ModifiersPool* modifiers,
310312
fSettings = settings;
311313
fCaps = caps;
312314
fInlineVarCounter = 0;
315+
fInlinedStatementCounter = 0;
313316
}
314317

315318
String Inliner::uniqueNameForInlineVar(const String& baseName, SymbolTable* symbolTable) {
@@ -465,6 +468,9 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
465468
}
466469
return nullptr;
467470
};
471+
472+
++fInlinedStatementCounter;
473+
468474
switch (statement.kind()) {
469475
case Statement::Kind::kBlock: {
470476
const Block& b = statement.as<Block>();
@@ -760,6 +766,11 @@ bool Inliner::isSafeToInline(const FunctionDefinition* functionDef) {
760766
return false;
761767
}
762768

769+
// Enforce a limit on inlining to avoid pathological cases. (inliner/ExponentialGrowth.sksl)
770+
if (fInlinedStatementCounter >= kInlinedStatementLimit) {
771+
return false;
772+
}
773+
763774
if (functionDef == nullptr) {
764775
// Can't inline something if we don't actually have its definition.
765776
return false;
@@ -1148,6 +1159,11 @@ bool Inliner::analyze(Program& program) {
11481159
return false;
11491160
}
11501161

1162+
// Enforce a limit on inlining to avoid pathological cases. (inliner/ExponentialGrowth.sksl)
1163+
if (fInlinedStatementCounter >= kInlinedStatementLimit) {
1164+
return false;
1165+
}
1166+
11511167
ProgramUsage* usage = program.fUsage.get();
11521168
InlineCandidateList candidateList;
11531169
this->buildCandidateList(program, &candidateList);
@@ -1200,6 +1216,11 @@ bool Inliner::analyze(Program& program) {
12001216
*candidate.fCandidateExpr = std::move(inlinedCall.fReplacementExpr);
12011217
madeChanges = true;
12021218

1219+
// Stop inlining if we've reached our hard cap on new statements.
1220+
if (fInlinedStatementCounter >= kInlinedStatementLimit) {
1221+
break;
1222+
}
1223+
12031224
// Note that nothing was destroyed except for the FunctionCall. All other nodes should
12041225
// remain valid.
12051226
}

src/sksl/SkSLInliner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class Inliner {
9595
const Program::Settings* fSettings = nullptr;
9696
const ShaderCapsClass* fCaps = nullptr;
9797
int fInlineVarCounter = 0;
98+
int fInlinedStatementCounter = 0;
9899
};
99100

100101
} // namespace SkSL

src/sksl/SkSLMain.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "src/sksl/ir/SkSLUnresolvedFunction.h"
1919

2020
#include <fstream>
21+
#include <limits.h>
2122
#include <stdarg.h>
2223
#include <stdio.h>
2324

@@ -183,6 +184,9 @@ static bool detect_shader_settings(const SkSL::String& text,
183184
if (settingsText.consumeSuffix(" NoInline")) {
184185
settings->fInlineThreshold = 0;
185186
}
187+
if (settingsText.consumeSuffix(" InlineThresholdMax")) {
188+
settings->fInlineThreshold = INT_MAX;
189+
}
186190
if (settingsText.consumeSuffix(" Sharpen")) {
187191
settings->fSharpenTextures = true;
188192
}

tests/sksl/inliner/ExponentialGrowth.sksl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/*#pragma settings InlineThresholdMax*/
2+
13
void fn1() { sk_FragColor.x = 0; }
24
void fn2() { fn1(); fn1(); fn1(); }
35
void fn3() { fn2(); fn2(); fn2(); }

0 commit comments

Comments
 (0)