[Mesa-dev] [PATCH 1/2] glsl: Avoid propagating incompatible type of initializer

Timothy Arceri tarceri at itsqueeze.com
Fri Sep 14 23:15:45 UTC 2018


Series:

Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>

Are there piglit tests to go with this?

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