Validate number of operands for if and switch. Instead of validating the specific operand for the `if` and `switch` instructions validate that there is only 1 instruction that it is valid. Fixes an issue where we can accidentally set multiple operands into an `if` where the operand is actually invalid. Fixed: 442245491 Change-Id: Ib8d9a5dd35535e55bbe76f4a55737721b59c3805 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/261215 Commit-Queue: dan sinclair <dsinclair@chromium.org> Auto-Submit: dan sinclair <dsinclair@chromium.org> Commit-Queue: Ryan Harrison <rharrison@chromium.org> Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/if.h b/src/tint/lang/core/ir/if.h index 993bc48..9b7aabe 100644 --- a/src/tint/lang/core/ir/if.h +++ b/src/tint/lang/core/ir/if.h
@@ -58,6 +58,8 @@ /// ``` class If : public Castable<If, ControlInstruction> { public: + /// The number of supported operands + static constexpr size_t kNumOperands = 1; /// The index of the condition operand static constexpr size_t kConditionOperandOffset = 0;
diff --git a/src/tint/lang/core/ir/switch.h b/src/tint/lang/core/ir/switch.h index 199e028..b6c44d9 100644 --- a/src/tint/lang/core/ir/switch.h +++ b/src/tint/lang/core/ir/switch.h
@@ -60,6 +60,8 @@ /// ``` class Switch final : public Castable<Switch, ControlInstruction> { public: + /// The number of supported operands + static constexpr size_t kNumOperands = 1; /// The offset in Operands() for the condition static constexpr size_t kConditionOperandOffset = 0;
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc index 334daea..82af55e 100644 --- a/src/tint/lang/core/ir/validator.cc +++ b/src/tint/lang/core/ir/validator.cc
@@ -3546,7 +3546,7 @@ void Validator::CheckIf(const If* if_) { CheckResults(if_); - CheckOperand(if_, If::kConditionOperandOffset); + CheckOperands(if_, If::kNumOperands); if (if_->Condition() && !if_->Condition()->Type()->Is<core::type::Bool>()) { AddError(if_, If::kConditionOperandOffset) << "condition type must be 'bool'"; @@ -3655,7 +3655,7 @@ void Validator::CheckSwitch(const Switch* s) { CheckResults(s); - CheckOperand(s, Switch::kConditionOperandOffset); + CheckOperands(s, Switch::kNumOperands); if (s->Condition() && !s->Condition()->Type()->IsIntegerScalar()) { auto* cond_ty = s->Condition() ? s->Condition()->Type() : nullptr;
diff --git a/src/tint/lang/core/ir/validator_flow_control_test.cc b/src/tint/lang/core/ir/validator_flow_control_test.cc index 4c89e1a..74823fd 100644 --- a/src/tint/lang/core/ir/validator_flow_control_test.cc +++ b/src/tint/lang/core/ir/validator_flow_control_test.cc
@@ -2189,7 +2189,8 @@ auto res = ir::Validate(mod); ASSERT_NE(res, Success); - EXPECT_THAT(res.Failure().reason, testing::HasSubstr(R"(error: switch: operand is undefined + EXPECT_THAT(res.Failure().reason, + testing::HasSubstr(R"(error: switch: expected exactly 1 operands, got 0 )")) << res.Failure(); }