Skip to content

Add bounds checking to OgaSequencesGetSequence C API functions#2260

Merged
jiafatom merged 3 commits into
mainfrom
fix/sequences-oob-bounds-check
Jul 10, 2026
Merged

Add bounds checking to OgaSequencesGetSequence C API functions#2260
jiafatom merged 3 commits into
mainfrom
fix/sequences-oob-bounds-check

Conversation

@jiafatom

@jiafatom jiafatom commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Description

OgaSequencesGetSequenceCount and OgaSequencesGetSequenceData accessed the underlying vector via operator[] without validating the sequence index. When a caller passes an index >= OgaSequencesCount(), this results in an out-of-bounds read of heap memory (undefined behavior), which can disclose adjacent heap contents.

This mirrors the validation already present in OgaAppendTokenToSequence, which checks the index before access.

Changes

  • OgaSequencesGetSequenceCount: return 0 when sequence >= size().
  • OgaSequencesGetSequenceData: return nullptr when sequence >= size().
    • Returning a value (instead of throwing) keeps a valid C ABI so no C++ exception crosses the C API boundary. This protects all language bindings (C, C++, Python, C#, Java) that route through these functions.
  • OgaCreateTensorFromBuffer: reject negative shape dimensions, guard the byte-count multiplication against size_t overflow, and reject a null shape_dims with a non-zero count (defense-in-depth).
  • Added CAPITests.SequencesOutOfBoundsAccess unit test (no model required) verifying valid access works and out-of-bounds indices return 0 / nullptr.

Testing

Built the library and unit tests, and ran:

[ RUN      ] CAPITests.AppendTokensToSequence
[       OK ] CAPITests.AppendTokensToSequence
[ RUN      ] CAPITests.SequencesOutOfBoundsAccess
[       OK ] CAPITests.SequencesOutOfBoundsAccess
[ RUN      ] CAPITests.MaxLength
[       OK ] CAPITests.MaxLength
[  PASSED  ] 3 tests.

Replaces #2257 (recreated as a non-fork branch so CI can run).

@jiafatom jiafatom requested a review from a team as a code owner July 2, 2026 23:36
Copilot AI review requested due to automatic review settings July 2, 2026 23:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the GenAI C API against out-of-bounds sequence access and improves defensive validation when creating tensors from user-provided buffers, reducing the risk of undefined behavior and potential heap data disclosure across all language bindings.

Changes:

  • Add bounds checks to OgaSequencesGetSequenceCount / OgaSequencesGetSequenceData to avoid OOB reads (return 0 / nullptr).
  • Strengthen OgaCreateTensorFromBuffer validation (null shape pointer, negative dims, and byte-count overflow guard).
  • Add a unit test covering out-of-bounds sequence access behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
test/c_api_tests.cpp Adds CAPITests.SequencesOutOfBoundsAccess to verify OOB indices return safe sentinel values.
src/ort_genai_c.cpp Adds bounds checks for sequence getters and adds shape/byte-count validation in OgaCreateTensorFromBuffer.

Comment thread src/ort_genai_c.cpp
Comment thread src/ort_genai_c.cpp
Comment thread src/ort_genai_c.cpp
jiafatom and others added 3 commits July 7, 2026 23:06
OgaSequencesGetSequenceCount and OgaSequencesGetSequenceData accessed the
underlying vector via operator[] without validating the sequence index,
allowing an out-of-bounds read when the caller supplied an index >= the
number of sequences. Return 0 / nullptr for out-of-bounds indices so no
C++ exception crosses the C API boundary.

Also harden OgaCreateTensorFromBuffer against negative dimensions and
byte-count multiplication overflow when computing the tensor size.

Add a CAPITests.SequencesOutOfBoundsAccess unit test covering the
out-of-bounds behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses review feedback: a caller of this C ABI entry point could pass
shape_dims=nullptr with a non-zero shape_dims_count, causing a null
dereference in the shape loop. Reject that combination explicitly before
constructing the span.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Document the out-of-bounds behavior of OgaSequencesGetSequenceCount
  (returns 0) and OgaSequencesGetSequenceData (returns nullptr) in the
  public C header so consumers don't misread it as a valid empty sequence.
- Guard against int64_t shape dimensions exceeding size_t range before
  casting in OgaCreateTensorFromBuffer, so the overflow check is not
  defeated by truncation on 32-bit builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jiafatom jiafatom force-pushed the fix/sequences-oob-bounds-check branch from 71f121a to a1a3720 Compare July 7, 2026 23:06
@jiafatom jiafatom merged commit b7348eb into main Jul 10, 2026
62 of 65 checks passed
@jiafatom jiafatom deleted the fix/sequences-oob-bounds-check branch July 10, 2026 00:58
tianleiwu pushed a commit that referenced this pull request Jul 11, 2026
## Description

`OgaSequencesGetSequenceCount` and `OgaSequencesGetSequenceData`
accessed the underlying vector via `operator[]` without validating the
`sequence` index. When a caller passes an index `>=
OgaSequencesCount()`, this results in an out-of-bounds read of heap
memory (undefined behavior), which can disclose adjacent heap contents.

This mirrors the validation already present in
`OgaAppendTokenToSequence`, which checks the index before access.

## Changes

- `OgaSequencesGetSequenceCount`: return `0` when `sequence >= size()`.
- `OgaSequencesGetSequenceData`: return `nullptr` when `sequence >=
size()`.
- Returning a value (instead of throwing) keeps a valid C ABI so no C++
exception crosses the C API boundary. This protects all language
bindings (C, C++, Python, C#, Java) that route through these functions.
- `OgaCreateTensorFromBuffer`: reject negative shape dimensions, guard
the byte-count multiplication against `size_t` overflow, and reject a
null `shape_dims` with a non-zero count (defense-in-depth).
- Added `CAPITests.SequencesOutOfBoundsAccess` unit test (no model
required) verifying valid access works and out-of-bounds indices return
`0` / `nullptr`.

## Testing

Built the library and unit tests, and ran:

```
[ RUN      ] CAPITests.AppendTokensToSequence
[       OK ] CAPITests.AppendTokensToSequence
[ RUN      ] CAPITests.SequencesOutOfBoundsAccess
[       OK ] CAPITests.SequencesOutOfBoundsAccess
[ RUN      ] CAPITests.MaxLength
[       OK ] CAPITests.MaxLength
[  PASSED  ] 3 tests.
```

Replaces #2257 (recreated as a non-fork branch so CI can run).

---------

Co-authored-by: Copilot <223556219+Copilot@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.

3 participants