Skip to content

Sync with Microsoft ONNX Runtime - 15072026#1200

Merged
hdharpure9922 merged 3 commits into
ovep-developfrom
sync_msft_15072026
Jul 15, 2026
Merged

Sync with Microsoft ONNX Runtime - 15072026#1200
hdharpure9922 merged 3 commits into
ovep-developfrom
sync_msft_15072026

Conversation

@ai-fw-intg

Copy link
Copy Markdown

Automated daily backmerge from ORT main to ovep-develop. No conflicts detected. Do NOT squash or rebase - use merge commit only.

kylo5aby and others added 3 commits July 14, 2026 09:33
… 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>

@hdharpure9922 hdharpure9922 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hdharpure9922
hdharpure9922 merged commit 8a7e952 into ovep-develop Jul 15, 2026
7 of 8 checks passed
@hdharpure9922
hdharpure9922 deleted the sync_msft_15072026 branch July 15, 2026 05:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants