Sync with Microsoft ONNX Runtime - 15072026#1200
Merged
Merged
Conversation
… builds (microsoft#29477) ### Description This PR allows `externalData` to be supplied as a `Blob`/`File` in JSPI builds. Instead of materializing the whole external data file in the JS heap and holding it through `_OrtCreateSession`, the WASM external data loader reads each initializer's byte range from the Blob on demand and releases it right after the CPU copy / GPU upload. The load-time CPU memory peak drops from the full model size to roughly the size of the largest single initializer. This follows the Blob/range-backed source approach suggested by the maintainers in microsoft#29455. `ExternalDataFileDescription.data` already accepts `Blob` in its type union, so there is no public API change ### Motivation and Context Fixes microsoft#29455. ### Measurements Phi-4-mini-instruct ONNX (q4f16, WebGPU EP, external data 1896 MB + 492 MB), Chrome / Windows, PTL | | whole-file (current) | Blob-backed (this PR) | |---|---|---| | JS heap peak during load | 2476 MB (held until session created) | 434 MB | | Tab process peak during load | 2893 MB | ~845 MB | | Model load time | 10.7 s | 3.9 s | load time benefits mainly from skipping the 2.4 GB in-heap materialization. Signed-off-by: Zhenwei Jin <zhenwei.jin@intel.com>
…s) (microsoft#29579) ## Summary The pooling operators (`MaxPool` / `AveragePool` / `LpPool` and the contrib `NhwcMaxPool`) did not fully validate attribute lengths and input ranks before indexing into per-spatial-dimension attribute vectors. On malformed models this could lead to out-of-bounds reads. This PR adds the missing input-validation guards so such models are rejected with clear errors instead of reading past the end of the attribute containers. Because all standard pooling execution providers (CPU / CUDA / ROCm / JS / WebGPU / XNNPACK / ACL) share `PoolBase` / `PoolAttributes`, the `pool_attributes.h` guards cover them all with a single change. `NhwcMaxPool` needs its own guard because it does not go through `PoolAttributes::SetOutputSize` and hand-writes its spatial loop. ## What changed, by file ### `onnxruntime/core/providers/cpu/nn/pool_attributes.h` - Validate `pads.size() == 2 * kernel_shape.size()` before indexing `pads` (F1). - Validate that the `kernel_shape` rank matches the input spatial rank in `InferOutputSize` before indexing `strides` / `kernel_shape` / `dilations` (F2). - Validate input rank `>= 2` in `SetOutputSize` before indexing the input shape (F5). - Remove the `int` truncation of the spatial dimension; use `int64` throughout (F3). - Wrap the residual output-size arithmetic in `SafeInt<int64_t>` to guard against overflow and enforce `out_size >= 0` (F4). - Give the `strides` length check an explicit error message (previously a bare condition). - Validate `MaxPool` `storage_order` is 0 (row-major) or 1 (column-major) at construction (F7). ### `onnxruntime/contrib_ops/cpu/quantization/nhwc_max_pool.cc` - `NhwcMaxPool` bypasses the shared `SetOutputSize` path and hand-writes its spatial loop, indexing `kernel_shape` / `strides` / `dilations` by dimension. Added a guard validating that the `kernel_shape` rank matches the input spatial rank before the loop. `Compute` returns `Status`, so this uses `ORT_RETURN_IF_NOT` (no-exception-build compatible), mirroring the existing guard in `fp16_pool.cc`. The `PoolAttributes` constructor already enforces that `strides` and `dilations` match `kernel_shape`, so guarding `kernel_shape` here covers all three indexed vectors. ### `onnxruntime/core/providers/cpu/fp16/fp16_pool.cc` - Fixed an incorrect loop bound in the malformed-`kernel_shape` diagnostic path: the error-message loop iterated with `TensorShape::Size()` (the element count, product of dims) while indexing the dimension array, which is bounded by the rank. Replaced it with `NumDimensions()` so the loop iterates the dims correctly. This `PoolFp16` kernel is ARM64-only (built under `MLAS_F16VEC_INTRINSICS_SUPPORTED`, i.e. non-Apple ARM64/ARM64EC) and the affected code runs only on the already-failing error path. Because the kernel is not compiled on x86 and the existing fp16 pool tests are gated on `USE_CUDA`/`USE_COREML` (exercising those EPs' kernels rather than this one), no x86 CI negative test can reach this path; the fix is validated by inspection. ### Tests Added 11 negative tests total, all using `kExpectFailure` and compatible with no-exception builds: - `pool_op_test.cc`: `MaxPool_PadsTooShort`, `AveragePool_PadsTooShort`, `LpPool_PadsTooShort`, `LpPool_KernelRankMismatch`, `AveragePool_NegativeOutputDim`, `MaxPool_PadsTooLong`, `MaxPool_StridesLengthMismatch`, `MaxPool_DilationsLengthMismatch`, `MaxPool_InputRankTooLow`, `MaxPool_InvalidStorageOrder`. - `nhwc_maxpool_op_test.cc`: `NhwcMaxPool KernelRankMismatch_S8`. ## Design note The `pads.size() == 2 * kernel_shape.size()` check is intentionally **unconditional** (not gated on `auto_pad`). Making it conditional on `auto_pad == NOTSET` would reopen the out-of-bounds indexing path for models that set `auto_pad` together with a malformed `pads` list. ## Testing All pooling and NHWC max-pool tests pass: **105 passed / 2 skipped (DML not built) / 0 failed**, with zero regression. ## Follow-ups (out of scope, tracked separately) - F6: `auto_pad` vs explicit `pads` mutual-exclusion per the ONNX spec — deferred due to backward-compatibility risk. - CUDA `narrow_cast<int>` truncation on `int64` dims — non-OOB. - Optional integer-domain ceil to remove a float path in `ComputeOutputSize`. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ai-fw-intg
requested review from
Jaswanth51,
ankitm3k,
jatinwadhwa921 and
vthaniel
July 14, 2026 20:35
hdharpure9922
self-requested a review
July 15, 2026 05:58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated daily backmerge from ORT main to ovep-develop. No conflicts detected. Do NOT squash or rebase - use merge commit only.