Skip to content

Cap VectorFstImpl::kMaxStates by StateId and validate start state before narrowing. - #350

Merged
copybara-service[bot] merged 1 commit into
mainfrom
copybara/995386187
Oct 7, 2026
Merged

copybara-service[bot] merged 1 commit into
mainfrom
copybara/995386187

Conversation

@copybara-service

Copy link
Copy Markdown

Cap VectorFstImpl::kMaxStates by StateId and validate start state before narrowing.

In VectorFstImpl<S> (lib/vector-fst.h):

  1. StateId (typename S::StateId) is int32_t for StdArc (max 2^31 - 1),
    whereas kMaxStates was 1LL << 52. If hdr.NumStates() (or the actual
    stream state count when hdr.NumStates() == kNoStateId) exceeded
    std::numeric_limits<StateId>::max(), the StateId state loop counter in
    Read() would overflow signed StateId.
  2. In VectorFstImpl::Read, hdr.Start() (int64_t) was passed to
    impl->BaseImpl::SetStart(hdr.Start()) (StateId) before the post-loop
    start-state range check, so a 64-bit value such as 1LL << 32 truncated to
    0 in 32-bit StateId and passed validation on any non-empty FST.

Fix by:

  • Capping VectorFstImpl::kMaxStates at
    std::min<int64_t>(0x10000000000000LL, std::numeric_limits<StateId>::max()).
  • Validating hdr.Start() as int64_t in VectorFstImpl::Read before calling
    SetStart, and guarding state == kMaxStates in the state-reading loop when
    hdr.NumStates() == kNoStateId.
  • Expanding VectorLimitsTest in fst_limits_test.cc to cover 64-bit state
    counts and start states that truncate into 32-bit StateId.

@copybara-service
copybara-service Bot force-pushed the copybara/995386187 branch 2 times, most recently from f8ebf1b to 72e8c16 Compare October 7, 2026 22:48
… before narrowing.

In `VectorFstImpl<S>` (`lib/vector-fst.h`):
1. `StateId` (`typename S::StateId`) is `int32_t` for `StdArc` (max `2^31 - 1`),
   whereas `kMaxStates` was `1LL << 52`. If `hdr.NumStates()` (or the actual
   stream state count when `hdr.NumStates() == kNoStateId`) exceeded
   `std::numeric_limits<StateId>::max()`, the `StateId state` loop counter in
   `Read()` would overflow signed `StateId`.
2. In `VectorFstImpl::Read`, `hdr.Start()` (`int64_t`) was passed to
   `impl->BaseImpl::SetStart(hdr.Start())` (`StateId`) before the post-loop
   start-state range check, so a 64-bit value such as `1LL << 32` truncated to
   `0` in 32-bit `StateId` and passed validation on any non-empty FST.

Fix by:
- Capping `VectorFstImpl::kMaxStates` at
  `std::min<int64_t>(0x10000000000000LL, std::numeric_limits<StateId>::max())`.
- Validating `hdr.Start()` as `int64_t` in `VectorFstImpl::Read` before calling
  `SetStart`, and guarding `state == kMaxStates` in the state-reading loop when
  `hdr.NumStates() == kNoStateId`.
- Expanding `VectorLimitsTest` in `fst_limits_test.cc` to cover 64-bit state
  counts and start states that truncate into 32-bit `StateId`.

PiperOrigin-RevId: 995416751
@copybara-service
copybara-service Bot merged commit 3d6e086 into main Oct 7, 2026
1 check passed
@copybara-service
copybara-service Bot deleted the copybara/995386187 branch October 7, 2026 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant