diff options
author | Kenneth Graunke <[email protected]> | 2016-11-12 11:27:17 -0800 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2016-11-12 22:08:15 -0800 |
commit | 9c676a64273f32c7fb3f2b6973399af1d7f24d46 (patch) | |
tree | 45b0f1920e63551e2d4c1e6512b10943bc6b27f2 | |
parent | 5debfeb86f524b06aa3b80f9855947a57b5f91e8 (diff) |
glsl: Fix assert fails when assignment expressions are in array sizes.
Karol Herbst's fuzzing efforts discovered that we would hit the
following assert:
assert(dummy_instructions.is_empty());
when processing an illegal array size expression of
float[(1=1)?1:1] t;
In do_assignment, we realized we needed an rvalue for (1 = 1), and
generated a temporary variable and assignment from the RHS. We've
already flagged an error (non-lvalue in assignment), and return a bogus
value as the rvalue. But process_array_size sees the bogus value, which
happened to be a constant expression, and rightly assumes that
processing a constant expression shouldn't have generated any code.
instructions.
To handle this, make do_assignment not generate any temps or assignments
when it's already raised an error - just return an error value directly.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98694
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Timothy Arceri <[email protected]>
-rw-r--r-- | src/compiler/glsl/ast_to_hir.cpp | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 24067b6ac0c..9b8678c04aa 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -1001,17 +1001,20 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, * i = j += 1; */ if (needs_rvalue) { - ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", - ir_var_temporary); - instructions->push_tail(var); - instructions->push_tail(assign(var, rhs)); - + ir_rvalue *rvalue; if (!error_emitted) { - ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var); + ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp", + ir_var_temporary); + instructions->push_tail(var); + instructions->push_tail(assign(var, rhs)); + + ir_dereference_variable *deref_var = + new(ctx) ir_dereference_variable(var); instructions->push_tail(new(ctx) ir_assignment(lhs, deref_var)); + rvalue = new(ctx) ir_dereference_variable(var); + } else { + rvalue = ir_rvalue::error_value(ctx); } - ir_rvalue *rvalue = new(ctx) ir_dereference_variable(var); - *out_rvalue = rvalue; } else { if (!error_emitted) |