Skip to content

Commit c91a36e

Browse files
ShabbyXAngle LUCI CQ
authored andcommitted
Translator: Validate negative index after comma
Expressions such as array[something,-1] where not validated because the index (something,-1) is not a constant, but they can be because only the right hand side of comma matters. Bug: chromium:465696600 Change-Id: I0f8dd115b4c3adefb81e9bafe12ee453bb96ebd1 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7224467 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>
1 parent e5f0293 commit c91a36e

File tree

2 files changed

+73
-14
lines changed

2 files changed

+73
-14
lines changed

src/compiler/translator/ParseContext.cpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6649,29 +6649,55 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
66496649
}
66506650
}
66516651

6652-
if (indexConstantUnion)
6652+
int index = 0;
6653+
bool outOfRangeIndexIsError = false;
6654+
6655+
// If the index is using the comma operator, descend to the right-most value, see if that's a
6656+
// constant. This is used for validating the index only, we can't constant fold the expression
6657+
// due to the left-hand-side of the comma.
6658+
TIntermTyped *commaRHS = indexExpression;
6659+
while (true)
66536660
{
6654-
// If an out-of-range index is not qualified as constant, the behavior in the spec is
6655-
// undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
6656-
// constant fold expressions that are not constant expressions). The most compatible way to
6657-
// handle this case is to report a warning instead of an error and force the index to be in
6658-
// the correct range.
6659-
bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
6660-
int index = 0;
6661-
if (indexConstantUnion->getBasicType() == EbtInt)
6661+
TIntermConstantUnion *constant = commaRHS->getAsConstantUnion();
6662+
if (constant)
66626663
{
6663-
index = indexConstantUnion->getIConst(0);
6664+
// If an out-of-range index is not qualified as constant, the behavior in the spec is
6665+
// undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
6666+
// constant fold expressions that are not constant expressions). The most compatible way
6667+
// to handle this case is to report a warning instead of an error and force the index to
6668+
// be in the correct range.
6669+
outOfRangeIndexIsError = commaRHS->getQualifier() == EvqConst;
6670+
index = 0;
6671+
if (constant->getBasicType() == EbtInt)
6672+
{
6673+
index = constant->getIConst(0);
6674+
}
6675+
else if (constant->getBasicType() == EbtUInt)
6676+
{
6677+
index = static_cast<int>(constant->getUConst(0));
6678+
}
6679+
6680+
if (index < 0)
6681+
{
6682+
outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative",
6683+
"[]");
6684+
}
6685+
break;
66646686
}
6665-
else if (indexConstantUnion->getBasicType() == EbtUInt)
6687+
6688+
TIntermBinary *asBinary = commaRHS->getAsBinaryNode();
6689+
if (asBinary == nullptr || asBinary->getOp() != EOpComma)
66666690
{
6667-
index = static_cast<int>(indexConstantUnion->getUConst(0));
6691+
break;
66686692
}
6693+
commaRHS = asBinary->getRight();
6694+
}
66696695

6696+
if (indexConstantUnion)
6697+
{
66706698
int safeIndex = -1;
6671-
66726699
if (index < 0)
66736700
{
6674-
outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
66756701
safeIndex = 0;
66766702
}
66776703

src/tests/gl_tests/GLSLValidationTest.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4712,6 +4712,39 @@ void main (void)
47124712
"GL_EXT_shader_framebuffer_fetch_non_coherent extension is used");
47134713
}
47144714

4715+
// Ensure that a negative index after a comma generates an error.
4716+
TEST_P(GLSLValidationTest_ES3, NegativeIndexAfterComma)
4717+
{
4718+
const char kFS[] = R"(#version 300 es
4719+
layout(location = 0) out mediump vec4 o_color;
4720+
uniform mediump float u;
4721+
uniform mediump vec4 u_color[4];
4722+
4723+
void main (void)
4724+
{
4725+
o_color = u_color[u,-2];
4726+
})";
4727+
4728+
validateError(GL_FRAGMENT_SHADER, kFS, "index expression is negative");
4729+
}
4730+
4731+
// Ensure that a negative const-variable index after a comma generates an error.
4732+
TEST_P(GLSLValidationTest_ES3, NegativeConstVarIndexAfterComma)
4733+
{
4734+
const char kFS[] = R"(#version 300 es
4735+
layout(location = 0) out mediump vec4 o_color;
4736+
uniform mediump float u;
4737+
uniform mediump vec4 u_color[4];
4738+
4739+
void main (void)
4740+
{
4741+
const int index = -2;
4742+
o_color = u_color[u,index];
4743+
})";
4744+
4745+
validateError(GL_FRAGMENT_SHADER, kFS, "index expression is negative");
4746+
}
4747+
47154748
// Validate that clip/cull distance extensions are not available in ESSL 100
47164749
TEST_P(GLSLValidationTest, ClipCullDistance)
47174750
{

0 commit comments

Comments
 (0)