Skip to content

Fix out-of-bounds read vulnerability in ArrayFeatureExtractor#27275

Merged
hariharans29 merged 3 commits intomainfrom
copilot/fix-heap-leak-in-array-feature-extractor
Feb 9, 2026
Merged

Fix out-of-bounds read vulnerability in ArrayFeatureExtractor#27275
hariharans29 merged 3 commits intomainfrom
copilot/fix-heap-leak-in-array-feature-extractor

Conversation

Copy link
Contributor

Copilot AI commented Feb 6, 2026

Description

ArrayFeatureExtractor was vulnerable to out-of-bounds reads when provided negative indices. The bounds check only validated upper bounds (y_data[i] >= stride) but not lower bounds, allowing negative values to read arbitrary heap memory.

Changes:

  • Added negative index validation in array_feature_extractor.cc line 76: y_data[i] < 0 || y_data[i] >= stride
  • Updated error message to clarify valid range: must be in [0, stride)
  • Added test case InvalidInputNegativeY to verify rejection of negative indices

Example exploitation:

# Previously allowed, causing heap leak
y_data = np.array([-10], dtype=np.int64)
results = session.run(["z"], {"x": x_data, "y": y_data})  # Reads unintended memory

Now returns INVALID_ARGUMENT with diagnostic message.

Motivation and Context

Security vulnerability allowing heap memory disclosure through negative index values bypassing bounds validation. The operator accesses x_data[y_data[j]] at line 98 without ensuring y_data[j] >= 0.

Original prompt

This section details on the original issue you should resolve

<issue_title>Out-of-Bounds Read Leading to Heap Leak</issue_title>
<issue_description>The vulnerability being exploited is a heap leak caused by an out-of-bounds read in ONNX Runtime’s ArrayFeatureExtractor operator. The root cause is insufficient bounds checking on the index input, allowing negative values to access unintended memory regions.

POC: Files shows code and code output

Per Copilot: 
Type: Out-of-bounds read (OOB read) in ONNX Runtime’s ArrayFeatureExtractor operator
Affected Version: ≤ 1.23.2 (latest at time of report)
Root Cause:
In the file onnxruntime/core/providers/cpu/ml/array_feature_extractor.cc, the code checks if y_data[i] <= stride (where stride is the total length), but does not check if y_data[i] >= 0.
This means a negative index can be used, causing an out-of-bounds read and leaking heap memory values.

Example: Supplying a negative value in y_data (e.g., y_data = [-10]) bypasses bounds checking and reads unintended memory, exposing heap data.

FINDERS Notes ------------

Detailed information is in the attachment, which includes complete steps to reproduce the problem.
Detailed information is in the attachment, which includes complete steps to reproduce the problem.

Save the model

import numpy as np
import onnx
from onnx import helper, TensorProto, checker

x_shape = [ 10,1]
x_dtype = TensorProto.INT64

y_shape = [1]
y_dtype = TensorProto.INT64

z_dtype = TensorProto.INT64
z_shape = [ 10,1]

node = helper.make_node(
op_type="ArrayFeatureExtractor",
inputs=["x", "y"],
outputs=["z"],
domain="ai.onnx.ml"
)

input_x = helper.make_tensor_value_info(
"x", x_dtype, x_shape
)

input_y = helper.make_tensor_value_info(
"y", y_dtype, y_shape
)

output_z = helper.make_tensor_value_info(
"z", z_dtype, z_shape
)

graph = helper.make_graph(
nodes=[node],
name="ArrayFeatureExtractor_Test",
inputs=[input_x, input_y],
outputs=[output_z]
)


opset_imports = [
helper.make_opsetid("", 15),
helper.make_opsetid("ai.onnx.ml", 3),
]

model = helper.make_model(
graph,
opset_imports=opset_imports,
producer_name="onnx-example"
)


onnx.save(model, "array_feature_extractor_manual.onnx")

Load the model

import onnxruntime as ort
import numpy as np
session = ort.InferenceSession("array_feature_extractor_manual.onnx", providers=["CPUExecutionProvider"])


x_data = np.arange(10, dtype=np.int64).reshape( 10,1)


y_data = np.array([-10], dtype=np.int64)

print(x_data)
print("?? Index:", y_data)


results = session.run(
["z"],
{"x": x_data, "y": y_data}
)

z_output = results[0]

print(z_output)
```</issue_description>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: hariharans29 <9969784+hariharans29@users.noreply.github.com>
Co-authored-by: hariharans29 <9969784+hariharans29@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix out-of-bounds read leading to heap leak in ONNX Runtime Fix out-of-bounds read vulnerability in ArrayFeatureExtractor Feb 6, 2026
Copilot AI requested a review from hariharans29 February 6, 2026 22:42
@hariharans29 hariharans29 marked this pull request as ready for review February 6, 2026 23:02
@hariharans29
Copy link
Member

/azp run Linux QNN CI Pipeline,Win_TRT_Minimal_CUDA_Test_CI,Windows ARM64 QNN CI Pipeline,Windows GPU Doc Gen CI Pipeline

@azure-pipelines
Copy link

Azure Pipelines successfully started running 4 pipeline(s).

@hariharans29 hariharans29 merged commit 7121f9a into main Feb 9, 2026
90 checks passed
@hariharans29 hariharans29 deleted the copilot/fix-heap-leak-in-array-feature-extractor branch February 9, 2026 00:20
tianleiwu pushed a commit that referenced this pull request Feb 12, 2026
### Description

ArrayFeatureExtractor was vulnerable to out-of-bounds reads when
provided negative indices. The bounds check only validated upper bounds
(`y_data[i] >= stride`) but not lower bounds, allowing negative values
to read arbitrary heap memory.

**Changes:**
- Added negative index validation in `array_feature_extractor.cc` line
76: `y_data[i] < 0 || y_data[i] >= stride`
- Updated error message to clarify valid range: `must be in [0, stride)`
- Added test case `InvalidInputNegativeY` to verify rejection of
negative indices

**Example exploitation:**
```python
# Previously allowed, causing heap leak
y_data = np.array([-10], dtype=np.int64)
results = session.run(["z"], {"x": x_data, "y": y_data})  # Reads unintended memory
```

Now returns `INVALID_ARGUMENT` with diagnostic message.

### Motivation and Context

Security vulnerability allowing heap memory disclosure through negative
index values bypassing bounds validation. The operator accesses
`x_data[y_data[j]]` at line 98 without ensuring `y_data[j] >= 0`.

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Out-of-Bounds Read Leading to Heap Leak</issue_title>
> <issue_description>The vulnerability being exploited is a heap leak
caused by an out-of-bounds read in ONNX Runtime’s ArrayFeatureExtractor
operator. The root cause is insufficient bounds checking on the index
input, allowing negative values to access unintended memory regions.
> 
> POC: Files shows code and code output
> 
> Per Copilot:&nbsp;
> Type: Out-of-bounds read (OOB read) in ONNX Runtime’s
ArrayFeatureExtractor operator
> Affected Version: ≤ 1.23.2 (latest at time of report)
> Root Cause:
> In the file
onnxruntime/core/providers/cpu/ml/array_feature_extractor.cc, the code
checks if y_data[i] &lt;= stride (where stride is the total length), but
does not check if y_data[i] &gt;= 0.
> This means a negative index can be used, causing an out-of-bounds read
and leaking heap memory values.
> 
> Example: Supplying a negative value in y_data (e.g., y_data = [-10])
bypasses bounds checking and reads unintended memory, exposing heap
data.
> 
> 
> FINDERS Notes ------------
> 
> Detailed information is in the attachment, which includes complete
steps to reproduce the problem.
> Detailed information is in the attachment, which includes complete
steps to reproduce the problem.
> 
> Save the model
> ```
> import numpy as np
> import onnx
> from onnx import helper, TensorProto, checker
> 
> x_shape = [ 10,1]
> x_dtype = TensorProto.INT64
> 
> y_shape = [1]
> y_dtype = TensorProto.INT64
> 
> z_dtype = TensorProto.INT64
> z_shape = [ 10,1]
> 
> node = helper.make_node(
> op_type="ArrayFeatureExtractor",
> inputs=["x", "y"],
> outputs=["z"],
> domain="ai.onnx.ml"
> )
> 
> input_x = helper.make_tensor_value_info(
> "x", x_dtype, x_shape
> )
> 
> input_y = helper.make_tensor_value_info(
> "y", y_dtype, y_shape
> )
> 
> output_z = helper.make_tensor_value_info(
> "z", z_dtype, z_shape
> )
> 
> graph = helper.make_graph(
> nodes=[node],
> name="ArrayFeatureExtractor_Test",
> inputs=[input_x, input_y],
> outputs=[output_z]
> )
> 
> 
> opset_imports = [
> helper.make_opsetid("", 15),
> helper.make_opsetid("ai.onnx.ml", 3),
> ]
> 
> model = helper.make_model(
> graph,
> opset_imports=opset_imports,
> producer_name="onnx-example"
> )
> 
> 
> onnx.save(model, "array_feature_extractor_manual.onnx")
> ```
> 
> Load the model
> ```
> import onnxruntime as ort
> import numpy as np
> session = ort.InferenceSession("array_feature_extractor_manual.onnx",
providers=["CPUExecutionProvider"])
> 
> 
> x_data = np.arange(10, dtype=np.int64).reshape( 10,1)
> 
> 
> y_data = np.array([-10], dtype=np.int64)
> 
> print(x_data)
> print("?? Index:", y_data)
> 
> 
> results = session.run(
> ["z"],
> {"x": x_data, "y": y_data}
> )
> 
> z_output = results[0]
> 
> print(z_output)
> ```</issue_description>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #27265

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: hariharans29 <9969784+hariharans29@users.noreply.github.com>
tianleiwu added a commit that referenced this pull request Feb 13, 2026
This cherry-picks the following commits for the 1.24.2 release:
- #27096
- #27077
- #26677
- #27238
- #27213
- #27256
- #27278
- #27275
- #27276
- #27216
- #27271
- #27299
- #27294
- #27266
- #27176
- #27126
- #27252

---------

Co-authored-by: Xiaofei Han <xiaofeihan@microsoft.com>
Co-authored-by: Jiajia Qin <jiajiaqin@microsoft.com>
Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com>
Co-authored-by: qti-monumeen <monumeen@qti.qualcomm.com>
Co-authored-by: Ankit Maheshkar <ankit.maheshkar@intel.com>
Co-authored-by: Eric Crawford <eric.r.crawford@intel.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: guschmue <22941064+guschmue@users.noreply.github.com>
Co-authored-by: Guenther Schmuelling <guschmue@microsoft.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: angelser <32746004+angelser@users.noreply.github.com>
Co-authored-by: Angela Serrano Brummett <angelser@microsoft.com>
Co-authored-by: Misha Chornyi <99709299+mc-nv@users.noreply.github.com>
Co-authored-by: hariharans29 <9969784+hariharans29@users.noreply.github.com>
Co-authored-by: eserscor <erscor@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Baiju Meswani <bmeswani@microsoft.com>
Co-authored-by: Adrian Lizarraga <adlizarraga@microsoft.com>
Co-authored-by: Ti-Tai Wang <titaiwang@microsoft.com>
Co-authored-by: bmehta001 <bmehta001@users.noreply.github.com>
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.

Out-of-Bounds Read Leading to Heap Leak

3 participants