[tint] Fix edge condition override array size oob
Array sizes in workgroup address space can be specified at pipeline
creation time via overrides. This means we need to validate all access
to these arrays after substitute overrides.
Bug:413427686
Change-Id: I12d241dc43938b038976c67de905e2f5a7a0d0b4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/243794
Commit-Queue: Peter McNeeley <petermcneeley@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/transform/substitute_overrides.cc b/src/tint/lang/core/ir/transform/substitute_overrides.cc
index 279bec9..1082f52 100644
--- a/src/tint/lang/core/ir/transform/substitute_overrides.cc
+++ b/src/tint/lang/core/ir/transform/substitute_overrides.cc
@@ -229,6 +229,14 @@
while (!to_replace.IsEmpty()) {
auto* inst = to_replace.Pop();
for (auto usage : inst->Result()->UsagesUnsorted()) {
+ // This is an edge case where we have to specifically verify bounds access for
+ // these new arrays for all usages.
+ if (NeedsEval(usage->instruction)) {
+ auto r = eval::Eval(b, usage->instruction);
+ if (r != Success) {
+ return r.Failure();
+ }
+ }
if (!usage->instruction->Is<core::ir::Let>()) {
continue;
}
diff --git a/src/tint/lang/core/ir/transform/substitute_overrides_test.cc b/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
index 16b1f13..4bd9d55 100644
--- a/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
+++ b/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
@@ -935,7 +935,7 @@
EXPECT_EQ(expect, str());
}
-TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeOutOfBounds) {
+TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeOverrideOutOfBounds) {
ir::Var* v = nullptr;
ir::Override* o = nullptr;
b.Append(mod.root_block, [&] {
@@ -981,6 +981,90 @@
EXPECT_EQ(result.Failure().reason, R"(error: index 7 out of bounds [0..4])");
}
+TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeLetOutOfBounds) {
+ ir::Var* v = nullptr;
+ b.Append(mod.root_block, [&] {
+ auto* x = b.Override("x", ty.u32());
+ x->SetOverrideId({2});
+
+ auto* cnt = ty.Get<core::ir::type::ValueArrayCount>(x->Result());
+ auto* ary = ty.Get<core::type::Array>(ty.u32(), cnt, 4_u, 4_u, 4_u, 4_u);
+ v = b.Var("v", ty.ptr(core::AddressSpace::kWorkgroup, ary, core::Access::kReadWrite));
+ });
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* p = b.Let("p", v);
+ auto* access = b.Access(ty.ptr<workgroup, u32>(), p, 7_u);
+ auto* load = b.Load(access);
+ b.Return(func, load);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %x:u32 = override undef @id(2)
+ %v:ptr<workgroup, array<u32, %x>, read_write> = var undef
+}
+
+%foo = func():u32 {
+ $B2: {
+ %p:ptr<workgroup, array<u32, %x>, read_write> = let %v
+ %5:ptr<workgroup, u32, read_write> = access %p, 7u
+ %6:u32 = load %5
+ ret %6
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ SubstituteOverridesConfig cfg{};
+ cfg.map[OverrideId{2}] = 5;
+ auto result = RunWithFailure(SubstituteOverrides, cfg);
+ ASSERT_NE(result, Success);
+ EXPECT_EQ(result.Failure().reason, R"(error: index 7 out of bounds [0..4])");
+}
+
+TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeOutOfBounds) {
+ ir::Var* v = nullptr;
+ b.Append(mod.root_block, [&] {
+ auto* x = b.Override("x", ty.u32());
+ x->SetOverrideId({2});
+
+ auto* cnt = ty.Get<core::ir::type::ValueArrayCount>(x->Result());
+ auto* ary = ty.Get<core::type::Array>(ty.u32(), cnt, 4_u, 4_u, 4_u, 4_u);
+ v = b.Var("v", ty.ptr(core::AddressSpace::kWorkgroup, ary, core::Access::kReadWrite));
+ });
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* access = b.Access(ty.ptr<workgroup, u32>(), v, 7_u);
+ auto* load = b.Load(access);
+ b.Return(func, load);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %x:u32 = override undef @id(2)
+ %v:ptr<workgroup, array<u32, %x>, read_write> = var undef
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<workgroup, u32, read_write> = access %v, 7u
+ %5:u32 = load %4
+ ret %5
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ SubstituteOverridesConfig cfg{};
+ cfg.map[OverrideId{2}] = 5;
+ auto result = RunWithFailure(SubstituteOverrides, cfg);
+ ASSERT_NE(result, Success);
+ EXPECT_EQ(result.Failure().reason, R"(error: index 7 out of bounds [0..4])");
+}
+
TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeExpression) {
b.Append(mod.root_block, [&] {
auto* x = b.Override("x", ty.u32());