[Stream] Bounds-check tied operand index in verifyTiedOperandEncodings (#24686)
## Summary
Bounds-check the tied-operand index in `verifyTiedOperandEncodings` so
an out-of-range `tied_operands` value is reported as a verification
error instead of indexing the operand-encodings array out of bounds.
## Context
`verifyTiedOperandEncodings` (used by tied stream ops such as
`stream.tensor.dispatch`) walks each result's tied operand and compares
`operandEncodings[operandIndex]` against the result encoding.
`operandIndex` is derived from the op's `tied_operands` attribute.
## Problem
The `tied_operands` value is not range-checked for this op before the
encoding lookup, so an index beyond the operand count reads
`operandEncodings` out of bounds. Such an index is reachable through the
generic assembly form (which bypasses the op's custom-format checks) —
for example, a dispatch with a single operand encoding but a
`tied_operands` entry pointing at operand 5:
```mlir
%0 = "stream.tensor.dispatch"(...) {
tied_operands = array<i64: 5>, ...
} : (...) -> ...
```
`operandIndex` (5) then indexes the single-element `operandEncodings`
out of bounds during verification.
## Fix
If `operandIndex >= operandEncodings.size()`, emit a verification error
(`tied operand index N is out of range of the M operand encoding(s)`)
instead of indexing out of bounds.
---
Disclosure: this contribution was authored with an AI coding assistant
(Claude) and reviewed before submission.
---------
Signed-off-by: Eylon Krause <eylon1909@gmail.com>diff --git a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
index 9901fc8..716cc37 100644
--- a/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
+++ b/compiler/src/iree/compiler/Dialect/Stream/IR/StreamOps.cpp
@@ -86,6 +86,17 @@
continue;
}
auto operandIndex = tiedOperand.value() - tiedOperandBase;
+ // The tied operand index comes from the tied_operands attribute and is not
+ // otherwise range-checked for this op. An out-of-range value can be written
+ // using the generic assembly form (e.g. `"stream.tensor.dispatch"(...)
+ // {tied_operands = array<i64: 5>}`), which bypasses the custom-format
+ // checks, so guard the encoding lookup below.
+ if (operandIndex >= operandEncodings.size()) {
+ return op->emitOpError()
+ << "tied operand index " << operandIndex
+ << " is out of range of the " << operandEncodings.size()
+ << " operand encoding(s)";
+ }
if (operandEncodings[operandIndex] != resultEncoding) {
return op->emitError()
<< "the " << operandIndex << "-th operandEncoding ("