summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2017-12-12 08:47:56 -0800
committerJason Ekstrand <[email protected]>2018-01-08 14:57:44 -0800
commit71ea4dded503cb68d40a144451bafaa80248c32b (patch)
tree98913c070a5cc4c9c488ab45c5bfa4f134f00686
parentd6a40993031b2ba088d92ce6ab832c50364d0f00 (diff)
spirv: Rework error checking for decorations
This reworks the error checking on our generic handling of decorations. The objective is to validate all of the SPIR-V assumptions we make up-front and convert redundant checks to compiled-out asserts. The most important part of this is to ensure that member decorations only occur on OpTypeStruct and that the member is never out-of-bounds. This way later code can assume that the member is sane and not have to worry about OOB array access due to a misplaced OpMemberDecorate. Reviewed-by: Lionel Landwerlin <[email protected]>
-rw-r--r--src/compiler/spirv/spirv_to_nir.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index 0d474957dc9..d195fbe09b9 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -376,15 +376,27 @@ _foreach_decoration_helper(struct vtn_builder *b,
if (dec->scope == VTN_DEC_DECORATION) {
member = parent_member;
} else if (dec->scope >= VTN_DEC_STRUCT_MEMBER0) {
- vtn_assert(parent_member == -1);
+ vtn_fail_if(value->value_type != vtn_value_type_type ||
+ value->type->base_type != vtn_base_type_struct,
+ "OpMemberDecorate and OpGroupMemberDecorate are only "
+ "allowed on OpTypeStruct");
+ /* This means we haven't recursed yet */
+ assert(value == base_value);
+
member = dec->scope - VTN_DEC_STRUCT_MEMBER0;
+
+ vtn_fail_if(member >= base_value->type->length,
+ "OpMemberDecorate specifies member %d but the "
+ "OpTypeStruct has only %u members",
+ member, base_value->type->length);
} else {
/* Not a decoration */
+ assert(dec->scope == VTN_DEC_EXECUTION_MODE);
continue;
}
if (dec->group) {
- vtn_assert(dec->group->value_type == vtn_value_type_decoration_group);
+ assert(dec->group->value_type == vtn_value_type_decoration_group);
_foreach_decoration_helper(b, base_value, member, dec->group,
cb, data);
} else {
@@ -414,7 +426,7 @@ vtn_foreach_execution_mode(struct vtn_builder *b, struct vtn_value *value,
if (dec->scope != VTN_DEC_EXECUTION_MODE)
continue;
- vtn_assert(dec->group == NULL);
+ assert(dec->group == NULL);
cb(b, value, dec, data);
}
}
@@ -435,7 +447,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
case SpvOpDecorate:
case SpvOpMemberDecorate:
case SpvOpExecutionMode: {
- struct vtn_value *val = &b->values[target];
+ struct vtn_value *val = vtn_untyped_value(b, target);
struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);
switch (opcode) {
@@ -444,12 +456,14 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
break;
case SpvOpMemberDecorate:
dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(w++);
+ vtn_fail_if(dec->scope < VTN_DEC_STRUCT_MEMBER0, /* overflow */
+ "Member argument of OpMemberDecorate too large");
break;
case SpvOpExecutionMode:
dec->scope = VTN_DEC_EXECUTION_MODE;
break;
default:
- vtn_fail("Invalid decoration opcode");
+ unreachable("Invalid decoration opcode");
}
dec->decoration = *(w++);
dec->literals = w;
@@ -474,6 +488,8 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
dec->scope = VTN_DEC_DECORATION;
} else {
dec->scope = VTN_DEC_STRUCT_MEMBER0 + *(++w);
+ vtn_fail_if(dec->scope < 0, /* Check for overflow */
+ "Member argument of OpGroupMemberDecorate too large");
}
/* Link into the list */
@@ -484,7 +500,7 @@ vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
}
default:
- vtn_fail("Unhandled opcode");
+ unreachable("Unhandled opcode");
}
}
@@ -561,7 +577,7 @@ struct_member_decoration_cb(struct vtn_builder *b,
if (member < 0)
return;
- vtn_assert(member < ctx->num_fields);
+ assert(member < ctx->num_fields);
switch (dec->decoration) {
case SpvDecorationNonWritable:
@@ -664,7 +680,10 @@ struct_member_matrix_stride_cb(struct vtn_builder *b,
{
if (dec->decoration != SpvDecorationMatrixStride)
return;
- vtn_assert(member >= 0);
+
+ vtn_fail_if(member < 0,
+ "The MatrixStride decoration is only allowed on members "
+ "of OpTypeStruct");
struct member_decoration_ctx *ctx = void_ctx;
@@ -686,8 +705,12 @@ type_decoration_cb(struct vtn_builder *b,
{
struct vtn_type *type = val->type;
- if (member != -1)
+ if (member != -1) {
+ /* This should have been handled by OpTypeStruct */
+ assert(val->type->base_type == vtn_base_type_struct);
+ assert(member >= 0 && member < val->type->length);
return;
+ }
switch (dec->decoration) {
case SpvDecorationArrayStride: