[Mesa-dev] [PATCH 1/2] glsl: Avoid propagating incompatible type of initializer
Danylo Piliaiev
danylo.piliaiev at gmail.com
Mon Sep 17 08:36:48 UTC 2018
Hi,
Thank you for the review.
On 9/15/18 2:15 AM, Timothy Arceri wrote:
> Series:
>
> Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
>
> Are there piglit tests to go with this?
Yes, there is a test "[PATCH] glsl-1.10: add a
'initialization-incompatible-type-propagation' test":
https://patchwork.freedesktop.org/patch/244676/
>
> On 15/8/18 10:46 pm, Danylo Piliaiev wrote:
>> do_assignment validated assigment but when rhs type was not compatible
>> it proceeded without issues and returned error_emitted = false.
>> On the other hand process_initializer expected do_assignment to always
>> return compatible type and never fail.
>>
>> As a result when variable was initialized with incompatible type
>> the type of variable changed to the incompatible one.
>> This manifested in unnecessary error messages and in one case in crash.
>>
>> Example GLSL:
>> vec4 tmp = vec2(0.0);
>> tmp.z -= 1.0;
>>
>> Past error messages:
>> initializer of type vec2 cannot be assigned to variable of type vec4
>> invalid swizzle / mask `z'
>> type mismatch
>> operands to arithmetic operators must be numeric
>>
>> After this patch:
>> initializer of type vec2 cannot be assigned to variable of type vec4
>>
>> In the other case when we initialize variable with incompatible struct,
>> accessing variable's field leaded to a crash. Example:
>> uniform struct {float field;} data;
>> ...
>> vec4 tmp = data;
>> tmp.x -= 1.0;
>>
>> After the patch there is only error line without a crash:
>> initializer of type #anon_struct cannot be assigned to variable of
>> type vec4
>>
>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107547
>>
>> Signed-off-by: Danylo Piliaiev <danylo.piliaiev at globallogic.com>
>> ---
>> src/compiler/glsl/ast_to_hir.cpp | 62 +++++++++++++++++---------------
>> 1 file changed, 33 insertions(+), 29 deletions(-)
>>
>> diff --git a/src/compiler/glsl/ast_to_hir.cpp
>> b/src/compiler/glsl/ast_to_hir.cpp
>> index 5d3f10b682..93e7c8ec33 100644
>> --- a/src/compiler/glsl/ast_to_hir.cpp
>> +++ b/src/compiler/glsl/ast_to_hir.cpp
>> @@ -1012,6 +1012,8 @@ do_assignment(exec_list *instructions, struct
>> _mesa_glsl_parse_state *state,
>> mark_whole_array_access(rhs);
>> mark_whole_array_access(lhs);
>> }
>> + } else {
>> + error_emitted = true;
>> }
>> /* Most callers of do_assignment (assign, add_assign,
>> pre_inc/dec,
>> @@ -4562,41 +4564,43 @@ process_initializer(ir_variable *var,
>> ast_declaration *decl,
>> /* Never emit code to initialize a uniform.
>> */
>> const glsl_type *initializer_type;
>> + bool error_emitted = false;
>> if (!type->qualifier.flags.q.uniform) {
>> - do_assignment(initializer_instructions, state,
>> - NULL,
>> - lhs, rhs,
>> - &result, true,
>> - true,
>> - type->get_location());
>> + error_emitted =
>> + do_assignment(initializer_instructions, state,
>> + NULL, lhs, rhs,
>> + &result, true, true,
>> + type->get_location());
>> initializer_type = result->type;
>> } else
>> initializer_type = rhs->type;
>> - var->constant_initializer =
>> rhs->constant_expression_value(mem_ctx);
>> - var->data.has_initializer = true;
>> + if (!error_emitted) {
>> + var->constant_initializer =
>> rhs->constant_expression_value(mem_ctx);
>> + var->data.has_initializer = true;
>> - /* If the declared variable is an unsized array, it must
>> inherrit
>> - * its full type from the initializer. A declaration such as
>> - *
>> - * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
>> - *
>> - * becomes
>> - *
>> - * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
>> - *
>> - * The assignment generated in the if-statement (below) will also
>> - * automatically handle this case for non-uniforms.
>> - *
>> - * If the declared variable is not an array, the types must
>> - * already match exactly. As a result, the type assignment
>> - * here can be done unconditionally. For non-uniforms the call
>> - * to do_assignment can change the type of the initializer (via
>> - * the implicit conversion rules). For uniforms the initializer
>> - * must be a constant expression, and the type of that expression
>> - * was validated above.
>> - */
>> - var->type = initializer_type;
>> + /* If the declared variable is an unsized array, it must
>> inherrit
>> + * its full type from the initializer. A declaration such as
>> + *
>> + * uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
>> + *
>> + * becomes
>> + *
>> + * uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
>> + *
>> + * The assignment generated in the if-statement (below) will
>> also
>> + * automatically handle this case for non-uniforms.
>> + *
>> + * If the declared variable is not an array, the types must
>> + * already match exactly. As a result, the type assignment
>> + * here can be done unconditionally. For non-uniforms the call
>> + * to do_assignment can change the type of the initializer (via
>> + * the implicit conversion rules). For uniforms the
>> initializer
>> + * must be a constant expression, and the type of that
>> expression
>> + * was validated above.
>> + */
>> + var->type = initializer_type;
>> + }
>> var->data.read_only = temp;
>> }
>>
More information about the mesa-dev
mailing list