# Unchecked slice or index panics on input

Lookup sentinels used as indexes, missing min-length checks, and wrong slice offsets on caller data

_Area: Smart contract access control and control flow. Seen in 4 disclosed reports; latest 2025-01-31. Updated 2026-11-02._

## How it works
Code takes a length, offset, or index derived from caller data (or from a lookup that can fail) and uses it directly to slice or index a buffer. The assumption that breaks is "the input is at least this long" or "the lookup always succeeds." When it doesn't, the runtime panics or reads the wrong bytes. In consensus code a panic halts the chain; in decoders a wrong offset silently produces a non-canonical result.

## Where it shows up
- A lookup returning `-1`/not-found whose result is used as an array index without a check [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md).
- A fixed-offset slice (e.g. `buf[:65]`) guarded only by a maximum-length check, never a minimum [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md).
- `BytesLib.toUintN`-style calls where the slice length argument doesn't match the field width [E3](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md).
- TLV/extension unpacking called on a raw account buffer that also contains non-TLV base data [E4](https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md).
- Any struct that snapshots a membership list at creation but later resolves members through a mutable registry [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md).

## How to review
For every slice/index on external data, confirm the exact invariant: the buffer length is checked against both a minimum and maximum before any fixed-offset slice [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md); every index from a lookup is validated against the container bounds before use, and the not-found sentinel is handled explicitly [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md); slice length arguments equal the field's true width [E3](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md); and decoders are called only on buffers of the expected shape (base data stripped before TLV unpack) [E4](https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md). Trace where the index/length originates versus where it is consumed; if they come from different sources (snapshot vs. live registry), the mismatch is the bug [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md).

## How finders spotted it
- Read every caller of a lookup that can return a sentinel, noting callers assume success; traced a path where the list and the address came from different sources, then wrote a unit test mixing the two operations to trigger the panic [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md).
- Reviewed length validation before a fixed 65-byte slice for a crypto primitive and saw only an upper bound [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md).
- Fuzzed a codec asserting `encode(decode(x)) == x`, finding malformed inputs that broke round-trip equality [E3](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md).
- Noticed one path used the correct TLV accessor while another unpacked TLV directly from the raw buffer [E4](https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md).

## Variants seen
- Sentinel `-1` from a lookup used as an index, panicking and stalling ballot finalization [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md).
- Missing minimum-length check before a fixed slice, panicking on the consensus path [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md).
- Wrong slice offsets in a decoder, making distinct encodings decode identically (malleability) [E3](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md).
- TLV unpack on a buffer containing non-TLV base data, so a filter always fails [E4](https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md).

## Impact and severity
Ranged from a stalled ballot that never finalizes [E1](https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md) and a chain-halting panic from one short vote extension [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md), to codec malleability [E3](https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md) and a permanently unusable bid filter [E4](https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md). Impact rises when the panic sits on a consensus or validator path, where a single malformed input reaches every node [E2](https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2023-11-zetachain%3AM-34.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2024-12-seda-protocol%3AH-19.md
- E3: https://bugbountylibrary.com/r/c4%3A2024-02-tapioca%3AM-26.md
- E4: https://bugbountylibrary.com/r/cantina%3Atensor_nov2024%3A3.2.4.md
