electron/patches/angle/cherry-pick-d0ee0197ddff.patch

209 lines
6.3 KiB
Diff

From d0ee0197ddff25fe1a9876511c07542ac483702d Mon Sep 17 00:00:00 2001
From: Shahbaz Youssefi <syoussefi@chromium.org>
Date: Wed, 03 May 2023 13:41:36 -0400
Subject: [PATCH] WebGL: Limit total size of private data
... not just individual arrays.
Bug: chromium:1431761
Change-Id: I721e29aeceeaf12c3f6a67b668abffb8dfbc89b0
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4503753
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
---
diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
index 6097b6d..2a033ad 100644
--- a/src/compiler/translator/ValidateTypeSizeLimitations.cpp
+++ b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
@@ -35,7 +35,9 @@
{
public:
ValidateTypeSizeLimitationsTraverser(TSymbolTable *symbolTable, TDiagnostics *diagnostics)
- : TIntermTraverser(true, false, false, symbolTable), mDiagnostics(diagnostics)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mDiagnostics(diagnostics),
+ mTotalPrivateVariablesSize(0)
{
ASSERT(diagnostics);
}
@@ -93,18 +95,33 @@
const bool isPrivate = variableType.getQualifier() == EvqTemporary ||
variableType.getQualifier() == EvqGlobal ||
variableType.getQualifier() == EvqConst;
- if (layoutEncoder.getCurrentOffset() > kMaxPrivateVariableSizeInBytes && isPrivate)
+ if (isPrivate)
{
- error(asSymbol->getLine(),
- "Size of declared private variable exceeds implementation-defined limit",
- asSymbol->getName());
- return false;
+ if (layoutEncoder.getCurrentOffset() > kMaxPrivateVariableSizeInBytes)
+ {
+ error(asSymbol->getLine(),
+ "Size of declared private variable exceeds implementation-defined limit",
+ asSymbol->getName());
+ return false;
+ }
+ mTotalPrivateVariablesSize += layoutEncoder.getCurrentOffset();
}
}
return true;
}
+ void validateTotalPrivateVariableSize()
+ {
+ if (mTotalPrivateVariablesSize > kMaxPrivateVariableSizeInBytes)
+ {
+ mDiagnostics->error(
+ TSourceLoc{},
+ "Total size of declared private variables exceeds implementation-defined limit",
+ "");
+ }
+ }
+
private:
void error(TSourceLoc loc, const char *reason, const ImmutableString &token)
{
@@ -213,6 +230,8 @@
TDiagnostics *mDiagnostics;
std::vector<int> mLoopSymbolIds;
+
+ size_t mTotalPrivateVariablesSize;
};
} // namespace
@@ -223,6 +242,7 @@
{
ValidateTypeSizeLimitationsTraverser validate(symbolTable, diagnostics);
root->traverse(&validate);
+ validate.validateTotalPrivateVariableSize();
return diagnostics->numErrors() == 0;
}
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
index e62c8fb..996bad1 100644
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -5271,11 +5271,12 @@
// fairly small array.
constexpr char kVSArrayOK[] =
R"(varying vec4 color;
-const int array_size = 1000;
+const int array_size = 500;
void main()
{
mat2 array[array_size];
- if (array[0][0][0] == 2.0)
+ mat2 array2[array_size];
+ if (array[0][0][0] + array2[0][0][0] == 2.0)
color = vec4(0.0, 1.0, 0.0, 1.0);
else
color = vec4(1.0, 0.0, 0.0, 1.0);
@@ -5353,6 +5354,103 @@
EXPECT_EQ(0u, program);
}
+// Reject attempts to allocate too much private memory.
+// This is an implementation-defined limit - crbug.com/1431761.
+TEST_P(WebGLCompatibilityTest, ValidateTotalPrivateSize)
+{
+ constexpr char kTooLargeGlobalMemory1[] =
+ R"(precision mediump float;
+
+// 1 MB / 16 bytes per vec4 = 65536
+vec4 array[32768];
+vec4 array2[32769];
+
+void main()
+{
+ if (array[0].x + array[1].x == 0.)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+
+ constexpr char kTooLargeGlobalMemory2[] =
+ R"(precision mediump float;
+
+// 1 MB / 16 bytes per vec4 = 65536
+vec4 array[32767];
+vec4 array2[32767];
+vec4 x, y, z;
+
+void main()
+{
+ if (array[0].x + array[1].x == x.w + y.w + z.w)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+
+ constexpr char kTooLargeGlobalAndLocalMemory1[] =
+ R"(precision mediump float;
+
+// 1 MB / 16 bytes per vec4 = 65536
+vec4 array[32768];
+
+void main()
+{
+ vec4 array2[32769];
+ if (array[0].x + array[1].x == 2.0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+
+ // Note: The call stack is not taken into account for the purposes of total memory calculation.
+ constexpr char kTooLargeGlobalAndLocalMemory2[] =
+ R"(precision mediump float;
+
+// 1 MB / 16 bytes per vec4 = 65536
+vec4 array[32768];
+
+float f()
+{
+ vec4 array2[16384];
+ return array2[0].x;
+}
+
+float g()
+{
+ vec4 array3[16383];
+ return array3[0].x;
+}
+
+float h()
+{
+ vec4 value;
+ float value2
+ return value.x + value2;
+}
+
+void main()
+{
+ if (array[0].x + f() + g() + h() == 2.0)
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+ else
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+})";
+
+ GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory1);
+ EXPECT_EQ(0u, program);
+
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory2);
+ EXPECT_EQ(0u, program);
+
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory1);
+ EXPECT_EQ(0u, program);
+
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory2);
+ EXPECT_EQ(0u, program);
+}
+
// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
// qualifiers.
TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)