Skip to content

Numba AdvancedSubtensor and AdvancedIncSubtensor don't bounds-check integer indices #2442

Description

@jessegrabowski

Under the numba backend, x[idx] and inc_subtensor(x[idx], v) with an out-of-range integer index read and write outside the array instead of raising. The C backend raises IndexError for the same graph.

import numpy as np, pytensor, pytensor.tensor as pt

x, idx = pt.vector("x"), pt.lvector("idx")
f = pytensor.function([pytensor.In(x, mutable=True), idx], pt.inc_subtensor(x[idx], 7.0), mode="NUMBA")

backing = np.zeros(12)
f(backing[:11], np.array([np.iinfo(np.int64).min]))
print(backing[11])  # 7.0: wrote one element past the end of the 11-element input

Indices 20 and -20 also return without error, while the C backend raises IndexError for all three.

Context: a Cast{int64} of a NaN float gives INT64_MIN on x86. After negative-index wraparound it stays negative, and the scatter writes one element past the end of its buffer. glibc later reports that as corrupted size vs. prev_size or double free or corruption, far from the Op that caused it.

Activity

  1. ricardoV94 commented on Sep 28, 2026

    @ricardoV94
    Member

    Context: a Cast{int64} of a NaN float gives INT64_MIN on x86. After negative-index wraparound it stays negative, and the scatter writes one element past the end of its buffer. glibc later reports that as corrupted size vs. prev_size or double free or corruption, far from the Op that caused it.

    Don't?

    The C backend raises IndexError for the same graph.

    Guess which backend is historically slow on indexing operations.

    Bound checks are expensive (or can be), and break vectorization. You can enable them with numba checkbounds flag or should be able to.

  2. ricardoV94 commented on Sep 28, 2026

    @ricardoV94
    Member
    import os
    os.environ["NUMBA_BOUNDSCHECK"] = "1"  # Set before importing Numba/PyTensor
    
    import numpy as np
    import pytensor
    import pytensor.tensor as pt
    
    x, idx = pt.vector("x"), pt.lvector("idx")
    f = pytensor.function(
        [pytensor.In(x, mutable=True), idx],
        pt.inc_subtensor(x[idx], 7.0),
        mode="NUMBA",
    )
    
    backing = np.zeros(12)
    f(backing[:11], np.array([np.iinfo(np.int64).min]))  # Raises IndexError
  3. added a commit that references this issue on Oct 11, 2026
    1deedc7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions