Clamped negative index access.

Fixed error that allowed negative index for accessing vector, matrix, and array. Now we report compile error and clamp the index to 0. Re-arranged code around it to handle negative index at the one location. BUG=crbug.com/239411 TEST=bug test case R=aedla@chromium.org, kbr@chromium.org Review URL: https://codereview.appspot.com/9193045 git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@2238 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent b40ad5a4
...@@ -267,43 +267,54 @@ postfix_expression ...@@ -267,43 +267,54 @@ postfix_expression
context->error(@2, " left of '[' is not of type array, matrix, or vector ", "expression"); context->error(@2, " left of '[' is not of type array, matrix, or vector ", "expression");
context->recover(); context->recover();
} }
if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { if ($3->getQualifier() == EvqConst) {
int index = $3->getAsConstantUnion()->getIConst(0);
if (index < 0) {
std::stringstream infoStream;
infoStream << index;
std::string info = infoStream.str();
context->error(@3, "negative index", info.c_str());
context->recover();
index = 0;
}
if ($1->getType().getQualifier() == EvqConst) {
if ($1->isArray()) { // constant folding for arrays if ($1->isArray()) { // constant folding for arrays
$$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, @2); $$ = context->addConstArrayNode(index, $1, @2);
} else if ($1->isVector()) { // constant folding for vectors } else if ($1->isVector()) { // constant folding for vectors
TVectorFields fields; TVectorFields fields;
fields.num = 1; fields.num = 1;
fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
$$ = context->addConstVectorNode(fields, $1, @2); $$ = context->addConstVectorNode(fields, $1, @2);
} else if ($1->isMatrix()) { // constant folding for matrices } else if ($1->isMatrix()) { // constant folding for matrices
$$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, @2); $$ = context->addConstMatrixNode(index, $1, @2);
} }
} else { } else {
if ($3->getQualifier() == EvqConst) {
if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) {
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'";
std::string extraInfo = extraInfoStream.str();
context->error(@2, "", "[", extraInfo.c_str());
context->recover();
} else {
if ($1->isArray()) { if ($1->isArray()) {
if ($1->getType().getArraySize() == 0) { if ($1->getType().getArraySize() == 0) {
if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) { if ($1->getType().getMaxArraySize() <= index) {
if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, @2)) if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), index, true, @2))
context->recover(); context->recover();
} else { } else {
if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, @2)) if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, @2))
context->recover(); context->recover();
} }
} else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) { } else if (index >= $1->getType().getArraySize()) {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; extraInfoStream << "array index out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
context->error(@2, "", "[", extraInfo.c_str()); context->error(@2, "", "[", extraInfo.c_str());
context->recover(); context->recover();
index = $1->getType().getArraySize() - 1;
} }
} else if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= index) {
std::stringstream extraInfoStream;
extraInfoStream << "field selection out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
context->error(@2, "", "[", extraInfo.c_str());
context->recover();
index = $1->getType().getNominalSize() - 1;
} }
$3->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
$$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, @2); $$ = context->intermediate.addIndex(EOpIndexDirect, $1, $3, @2);
} }
} else { } else {
...@@ -311,10 +322,8 @@ postfix_expression ...@@ -311,10 +322,8 @@ postfix_expression
context->error(@2, "", "[", "array must be redeclared with a size before being indexed with a variable"); context->error(@2, "", "[", "array must be redeclared with a size before being indexed with a variable");
context->recover(); context->recover();
} }
$$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, @2); $$ = context->intermediate.addIndex(EOpIndexIndirect, $1, $3, @2);
} }
}
if ($$ == 0) { if ($$ == 0) {
ConstantUnion *unionArray = new ConstantUnion[1]; ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f); unionArray->setFConst(0.0f);
...@@ -327,17 +336,16 @@ postfix_expression ...@@ -327,17 +336,16 @@ postfix_expression
if ($1->getType().getQualifier() == EvqConst) if ($1->getType().getQualifier() == EvqConst)
$$->getTypePointer()->setQualifier(EvqConst); $$->getTypePointer()->setQualifier(EvqConst);
} else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst) } else if ($1->isMatrix()) {
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize())); TQualifier qualifier = $1->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
else if ($1->isMatrix()) $$->setType(TType($1->getBasicType(), $1->getPrecision(), qualifier, $1->getNominalSize()));
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize())); } else if ($1->isVector()) {
else if ($1->isVector() && $1->getType().getQualifier() == EvqConst) TQualifier qualifier = $1->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst)); $$->setType(TType($1->getBasicType(), $1->getPrecision(), qualifier));
else if ($1->isVector()) } else {
$$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
else
$$->setType($1->getType()); $$->setType($1->getType());
} }
}
| function_call { | function_call {
$$ = $1; $$ = $1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment