Fix out-of-bounds read when a Loop/Scan body input is also an initializer - #32609
Akshay Sonawane (apsonawane) merged 2 commits into
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟡 Changes recommended
The regression case still reaches an ORT_ENFORCE that aborts exception-disabled builds instead of returning a clean error.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Prevents out-of-bounds access while mapping Loop/Scan parent inputs to subgraph inputs.
Changes:
- Selects a cardinality-matching subgraph input list and validates bounds.
- Adds a Loop regression test for initializer-backed body inputs.
File summaries
| File | Description |
|---|---|
onnxruntime/core/framework/session_state.cc |
Hardens subgraph input mapping. |
onnxruntime/test/providers/cpu/controlflow/loop_test.cc |
Adds the regression test. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced (auto)
Note
Copilot is running an experiment and ran this review at Balanced.
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Tianlei Wu (@tianleiwu) Can you help review this PR or help find suitable reviewers? Thanks. |
There was a problem hiding this comment.
🟢 Approval recommended
The memory-safety fix is correct and covered; only non-blocking comment cleanup remains.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced (auto)
Note
Copilot is running an experiment and ran this review at Balanced.
There was a problem hiding this comment.
🟡 Changes recommended
The implemented rejection behavior materially differs from the matching-input-list strategy stated in the PR description.
Get a fresh assessment by requesting another Copilot review.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
|
Wei Wang (@wangw-1991) can you review the one copilot comment |
Done. Please help merge this PR if no other issues, thanks. |
09dfa6a
into
microsoft:main
This cherry-picks the following commits for the release: * #32610 * #32633 * #32641 * #32611 * #32609 * #32607 * #32679 * #32681 * #32666 CI fixes: * #32491 (installs `uuid-dev` for the Linux minimal-build CoreML job; that check also fails on the `rel-1.28.3` base) * Raise the Android minimal baseline binary-size threshold from 1,440,768 to 1,443,840 bytes (release branch only). The checks added by these fixes grow the minimal build from 1,440,538 to 1,443,098 bytes (+2,560). All picks except #32607 applied cleanly with `git cherry-pick -x`, in the order they merged into main (#32666 was added afterward). #32607 required a manual backport because `bert_defs.cc` has diverged on main since 1.28 branched: - `GroupQueryAttention` / `SparseAttention`: backported as-is (`total_sequence_length_index` of 6 / 7, plus the single-element check). The GQA call site in 1.28 has no `sliding_window_cache`, so it only gets the new argument. - `CausalConvWithState`: the 1.28 schema predates `channels_last`, `state_window`, and `dilation`. Only the `ndim` in [1, 3] check and the `weight`/`input` rank == `ndim + 2` checks are backported. These match what the 1.28 CPU kernel already enforces. `ChannelsLastInputRankBelowThreeIsRejected` is dropped. - `GatedDeltaNet`: this op does not exist on 1.28.3, so its hunk and test are dropped. Validation (Windows x64, CPU EP, RelWithDebInfo): - All 14 regression tests added by these PRs pass. - `onnxruntime_test_all`: 1848 tests (including #32666's `PluginCopiesForwardStreams`), 0 failures. - `onnxruntime_provider_test`: 5370 tests, 0 failures. --------- Co-authored-by: Wei Wang <wei4.wang@intel.com> Co-authored-by: shiyi <shiyi.zou@intel.com> Co-authored-by: Bin Miao <bin.miao@intel.com> Co-authored-by: Bryan B <bryan.bernhart@intel.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: tianleiwu <30328909+tianleiwu@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Xiaofei Han <xiaofeihan@microsoft.com>
Problem
OuterScopeNodeArgLocationAccumulator(session_state.cc) maps a Loop/Scan node's explicit inputs onto the subgraph's inputs usingGraphViewer::GetInputs(), which excludes initializer-backed inputs. When a body declares an input that is also abody initializer,
GetInputs()is shorter than the parent node's input list, so indexingsubgraph_inputs[arg_idx]reads past the end of the vector and dereferences an invalidNodeArgpointer during session initialization. This causes a crash / heap out-of-bounds read (observable under ASan) when loading a malformed model containing such a Loop/Scan.Fix
In the Loop/Scan≥9 branch of
OuterScopeNodeArgLocationAccumulator:subgraph.GetInputs().size()does not equal the parent node's input count, return anINVALID_GRAPHstatus naming the parent node and both counts, instead of indexing. When the size difference is explained by initializer-backed inputs (GetInputsIncludingInitializers()is larger), the message adds a hint pointing at that as the cause.Loop.BodyInputAlsoInitializerIsRejectedtest: builds a Loop whose body inputstate_inis also a body initializer, and assertsInferenceSession::Initialize()fails withINVALID_GRAPHand the expected message — i.e. rejected cleanly rather than crashing. The test asserts on the status code and message text on purpose, so that it keeps covering this path rather than silently falling through to theORT_ENFORCEdownstream.