mirror of https://github.com/electron/electron
209 lines
6.3 KiB
Diff
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)
|