Track max accessed array element, reject additional out-of-bounds accesses
For unsized arrays, we can't flag out-of-bounds accesses until the array is redeclared with a size. Track the maximum accessed element and generate an error if the declaration specifies a size that would cause that access to be out-of-bounds. This causes the following tests to pass: glslparsertest/shaders/array10.frag
This commit is contained in:
parent
27e3cf8c0d
commit
b8a21cc6df
|
@ -898,13 +898,29 @@ ast_expression::hir(exec_list *instructions,
|
|||
|
||||
error_emitted = op[0]->type->is_error() || op[1]->type->is_error();
|
||||
|
||||
result = new ir_dereference(op[0], op[1]);
|
||||
ir_dereference *const lhs = op[0]->as_dereference();
|
||||
ir_instruction *array;
|
||||
if ((lhs != NULL)
|
||||
&& (lhs->mode == ir_dereference::ir_reference_variable)) {
|
||||
result = new ir_dereference(lhs->var, op[1]);
|
||||
|
||||
delete op[0];
|
||||
array = lhs->var;
|
||||
} else {
|
||||
result = new ir_dereference(op[0], op[1]);
|
||||
array = op[0];
|
||||
}
|
||||
|
||||
/* Do not use op[0] after this point. Use array.
|
||||
*/
|
||||
op[0] = NULL;
|
||||
|
||||
|
||||
if (error_emitted)
|
||||
break;
|
||||
|
||||
/* FINISHME: Handle vectors and matrices accessed with []. */
|
||||
if (!op[0]->type->is_array()) {
|
||||
if (!array->type->is_array()) {
|
||||
_mesa_glsl_error(& index_loc, state,
|
||||
"cannot dereference non-array");
|
||||
error_emitted = true;
|
||||
|
@ -937,11 +953,11 @@ ast_expression::hir(exec_list *instructions,
|
|||
* declared size. It is also illegal to index an array with a
|
||||
* negative constant expression."
|
||||
*/
|
||||
if ((op[0]->type->array_size() > 0)
|
||||
&& (op[0]->type->array_size() <= idx)) {
|
||||
if ((array->type->array_size() > 0)
|
||||
&& (array->type->array_size() <= idx)) {
|
||||
_mesa_glsl_error(& loc, state,
|
||||
"array index must be < %u",
|
||||
op[0]->type->array_size());
|
||||
array->type->array_size());
|
||||
error_emitted = true;
|
||||
}
|
||||
|
||||
|
@ -950,6 +966,10 @@ ast_expression::hir(exec_list *instructions,
|
|||
"array index must be >= 0");
|
||||
error_emitted = true;
|
||||
}
|
||||
|
||||
ir_variable *const v = array->as_variable();
|
||||
if ((v != NULL) && (unsigned(idx) > v->max_array_access))
|
||||
v->max_array_access = idx;
|
||||
}
|
||||
|
||||
if (error_emitted)
|
||||
|
@ -1265,9 +1285,15 @@ ast_declarator_list::hir(exec_list *instructions,
|
|||
* FINISHME: declarations. It's not 100% clear whether this is
|
||||
* FINISHME: required or not.
|
||||
*/
|
||||
/* FINISHME: Check that the array hasn't already been accessed
|
||||
* FINISHME: beyond the newly defined bounds.
|
||||
*/
|
||||
|
||||
if (var->type->array_size() <= earlier->max_array_access) {
|
||||
YYLTYPE loc = this->get_location();
|
||||
|
||||
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
|
||||
"previous access",
|
||||
earlier->max_array_access);
|
||||
}
|
||||
|
||||
earlier->type = var->type;
|
||||
delete var;
|
||||
var = NULL;
|
||||
|
|
2
ir.cpp
2
ir.cpp
|
@ -246,7 +246,7 @@ ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length)
|
|||
|
||||
|
||||
ir_variable::ir_variable(const struct glsl_type *type, const char *name)
|
||||
: ir_instruction(), read_only(false), centroid(false), invariant(false),
|
||||
: max_array_access(0), read_only(false), centroid(false), invariant(false),
|
||||
mode(ir_var_auto), interpolation(ir_var_smooth)
|
||||
{
|
||||
this->type = type;
|
||||
|
|
8
ir.h
8
ir.h
|
@ -121,6 +121,7 @@ public:
|
|||
{
|
||||
ir_variable *var = new ir_variable(type, name);
|
||||
|
||||
var->max_array_access = this->max_array_access;
|
||||
var->read_only = this->read_only;
|
||||
var->centroid = this->centroid;
|
||||
var->invariant = this->invariant;
|
||||
|
@ -132,6 +133,13 @@ public:
|
|||
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Highest element accessed with a constant expression array index
|
||||
*
|
||||
* Not used for non-array variables.
|
||||
*/
|
||||
unsigned max_array_access;
|
||||
|
||||
unsigned read_only:1;
|
||||
unsigned centroid:1;
|
||||
unsigned invariant:1;
|
||||
|
|
Loading…
Reference in New Issue