已关闭
[ArkWeb][安全][上游社区漏洞修复][BUG-537835609] fragData逗号校验 #467
[ArkWeb][安全][上游社区漏洞修复][BUG-537835609] fragData逗号校验 #467
已关闭
创建于 18 天前关闭于 17 天前
4 个文件变更+102-0
@@ -370,6 +370,28 @@ bool IsESSL100ConstantExpression(TIntermNode *node)
370{370{
371 return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;371 return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;
372}372}
373+ 
374+bool IsWholeArrayFragDataUsed(TIntermTyped *node)
375+{
376+ if (node->getQualifier() == EvqFragData)
377+ {
378+ return true;
379+ }
380+ 
381+ TIntermBinary *asBinary = node->getAsBinaryNode();
382+ if (asBinary != nullptr && asBinary->getOp() == EOpComma)
383+ {
384+ return IsWholeArrayFragDataUsed(asBinary->getRight());
385+ }
386+ 
387+ // Either this is not ESSL 100 (where gl_FragData may be used), or gl_FragData is not used as a
388+ // whole array.
389+ //
390+ // Note: ESSL 100 does not allow arrays in ternary operator, so there is no need to check for
391+ // TIntermTernary here for a whole-array use of gl_FragData.
392+ return false;
393+}
394+ 
373} // namespace395} // namespace
374 396 
375// This tracks each binding point's current default offset for inheritance of subsequent397// This tracks each binding point's current default offset for inheritance of subsequent
@@ -2784,6 +2806,22 @@ void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandid
2784 }2806 }
2785}2807}
2786 2808 
2809+void TParseContext::functionCallFragDataCheck(const TFunction *fnCandidate,
2810+ TIntermAggregate *fnCall)
2811+{
2812+ for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
2813+ {
2814+ TIntermTyped *argument = (*fnCall->getSequence())[i]->getAsTyped();
2815+ if (IsWholeArrayFragDataUsed(argument))
2816+ {
2817+ // The whole array is passed to the function. For validation purposes, assume all
2818+ // indices are accessed in the function.
2819+ ASSERT(argument->getType().isArray());
2820+ mMaxFragDataArrayIndexUsed = argument->getType().getOutermostArraySize() - 1;
2821+ }
2822+ }
2823+}
2824+ 
2787void TParseContext::checkInvariantVariableQualifier(bool invariant,2825void TParseContext::checkInvariantVariableQualifier(bool invariant,
2788 const TQualifier qualifier,2826 const TQualifier qualifier,
2789 const TSourceLoc &invariantLocation)2827 const TSourceLoc &invariantLocation)
@@ -9305,6 +9343,7 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup *
9305 callNode->setLine(loc);9343 callNode->setLine(loc);
9306 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);9344 checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
9307 functionCallRValueLValueErrorCheck(fnCandidate, callNode);9345 functionCallRValueLValueErrorCheck(fnCandidate, callNode);
9346+ functionCallFragDataCheck(fnCandidate, callNode);
9308 9347 
9309 mCallGraph[mCurrentFunction].insert(fnCandidate);9348 mCallGraph[mCurrentFunction].insert(fnCandidate);
9310 mIRBuilder.callFunction(mFunctionToId.at(fnCandidate));9349 mIRBuilder.callFunction(mFunctionToId.at(fnCandidate));
@@ -214,6 +214,7 @@ class TParseContext : angle::NonCopyable
214 bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,214 bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
215 const TLayoutQualifier &layoutQualifier);215 const TLayoutQualifier &layoutQualifier);
216 void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);216 void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
217+ void functionCallFragDataCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
217 void checkInvariantVariableQualifier(bool invariant,218 void checkInvariantVariableQualifier(bool invariant,
218 const TQualifier qualifier,219 const TQualifier qualifier,
219 const TSourceLoc &invariantLocation);220 const TSourceLoc &invariantLocation);
@@ -0,0 +1,34 @@
1+# Translator Unit Tests
2+ 
3+This directory contains historical unit tests for the ANGLE translator. Barring a few cases, they
4+should be considered deprecated. **Do not add new tests to this directory.**
5+ 
6+The existing translator tests are severely limited in what they test. They often verify translation
7+by asserting that a substring exists in the translated source or a node is found in the AST.
8+However, neither is sufficient to ensure the transformations are done correctly. Often issues are
9+discovered only when the shaders are used in a draw call and the translated source is given to the
10+native driver.
11+ 
12+Furthermore, with the built-in assumptions about the way the AST works, these tests are incompatible
13+with the upcoming IR.
14+ 
15+Instead, add end-to-end tests:
16+ 
17+* They can be easily tested on every backend
18+* Functional testing with a draw call ensures the transformations are correct
19+* Using the `GL_ANGLE_translated_shader_source` extension, we can still verify the output is as
20+ expected. This is a maintenance burden however and best avoided unless there is no _functional_
21+ way to verify the transformation is done correctly, e.g. if the transformation works around
22+ undefined behavior which can't be reliably tested.
23+ 
24+To test translator validation, add new tests to `GLSLValidationTest.cpp`, which not only verifies
25+that compilation fails, but also has facilities to ensure the failure reason is as expected (and
26+not, for example, a typo in the test)
27+ 
28+To test transformations, add new tests to `GLSLTest.cpp` that would fail if the transformation in
29+question is not done. By using ANGLE features to control the translator flag in question, the
30+transformation can be force-enabled in a test suite, e.g. by instantiating with
31+`ES3_OPENGL().enable(Feature::ScalarizeVecAndMatConstructorArgs)`
32+ 
33+To test that the output includes a specific text, if there is no better form of verification, add
34+new tests to `GLSLOutputTest.cpp`.
@@ -4385,6 +4385,34 @@ void main() {
4385 "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT when gl_SecondaryFragDataEXT is used");4385 "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT when gl_SecondaryFragDataEXT is used");
4386}4386}
4387 4387 
4388+// Shader that writes to SecondaryFragData and passes FragData to a function.
4389+TEST_P(GLSLValidationTest, BlendFuncExtendedPassFragDataToFunctionInCommaExpr)
4390+{
4391+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_blend_func_extended"));
4392+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_draw_buffers"));
4393+ 
4394+ GLint maxDrawBuffers = 0, maxDualSourceDrawBuffers = 0;
4395+ glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers);
4396+ glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
4397+ ANGLE_SKIP_TEST_IF(maxDualSourceDrawBuffers == maxDrawBuffers);
4398+ 
4399+ constexpr char kFS[] = R"(#extension GL_EXT_draw_buffers : require
4400+#extension GL_EXT_blend_func_extended : require
4401+precision mediump float;
4402+void f(vec4 fragData[gl_MaxDrawBuffers])
4403+{
4404+ fragData[0] = vec4(0.1);
4405+}
4406+void main() {
4407+ vec4 data[gl_MaxDrawBuffers];
4408+ f((data, gl_FragData));
4409+ gl_SecondaryFragDataEXT[0] = vec4(1.0);
4410+})";
4411+ validateError(GL_FRAGMENT_SHADER, kFS,
4412+ "array index for gl_FragData must be less than "
4413+ "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT when gl_SecondaryFragDataEXT is used");
4414+}
4415+ 
4388// Shader that writes to FragData at an index >= than gl_MaxDualSourceDrawBuffersEXT is fine if4416// Shader that writes to FragData at an index >= than gl_MaxDualSourceDrawBuffersEXT is fine if
4389// SecondaryFragData is not used.4417// SecondaryFragData is not used.
4390TEST_P(GLSLValidationTest, BlendFuncExtendedDataArrayOnly)4418TEST_P(GLSLValidationTest, BlendFuncExtendedDataArrayOnly)