glsl/linker: fix output variable overlap check
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sun, 17 Sep 2017 16:25:39 +0000 (18:25 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Wed, 20 Sep 2017 13:35:57 +0000 (15:35 +0200)
Prevent an overflow caused by too many output variables. To limit the
scope of the issue, write to the assigned array only for the non-ES
fragment shader path, which is the only place where it's needed.

Since the function will bail with an error when output variables with
overlapping components are found, (max # of FS outputs) * 4 is an upper
limit to the space we need.

Found by address sanitizer.

Fixes dEQP-GLES3.functional.attribute_location.bind_aliasing.*

Cc: mesa-stable@lists.freedesktop.org
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
src/compiler/glsl/linker.cpp

index 141bf4303704e5664aa4b4e6a258d472f48644ed..422b8ecd13e58993fd324d1653cbc32822e24f2f 100644 (file)
@@ -2651,12 +2651,14 @@ assign_attribute_or_color_locations(void *mem_ctx,
    } to_assign[32];
    assert(max_index <= 32);
 
-   /* Temporary array for the set of attributes that have locations assigned.
+   /* Temporary array for the set of attributes that have locations assigned,
+    * for the purpose of checking overlapping slots/components of (non-ES)
+    * fragment shader outputs.
     */
-   ir_variable *assigned[16];
+   ir_variable *assigned[12 * 4]; /* (max # of FS outputs) * # components */
+   unsigned assigned_attr = 0;
 
    unsigned num_attr = 0;
-   unsigned assigned_attr = 0;
 
    foreach_in_list(ir_instruction, node, sh->ir) {
       ir_variable *const var = node->as_variable();
@@ -2882,6 +2884,12 @@ assign_attribute_or_color_locations(void *mem_ctx,
                         }
                      }
                   }
+
+                  /* At most one variable per fragment output component should
+                   * reach this. */
+                  assert(assigned_attr < ARRAY_SIZE(assigned));
+                  assigned[assigned_attr] = var;
+                  assigned_attr++;
                } else if (target_index == MESA_SHADER_FRAGMENT ||
                           (prog->IsES && prog->data->Version >= 300)) {
                   linker_error(prog, "overlapping location is assigned "
@@ -2921,9 +2929,6 @@ assign_attribute_or_color_locations(void *mem_ctx,
                double_storage_locations |= (use_mask << attr);
          }
 
-         assigned[assigned_attr] = var;
-         assigned_attr++;
-
          continue;
       }