# Unvalidated parser index or chunk id

Input-derived chunk id or index used to index a table or buffer without a range or length check

_Area: Memory corruption and native code. Seen in 3 disclosed reports; latest 2023-08-17. Updated 2026-10-24._

## How it works
A parser takes an id, index or offset straight from the input and uses it to look up a table entry or address a buffer, assuming the value is in range. The assumption breaks because the input is attacker-controlled: the value can be outside the valid set, or the buffer can be shorter than the code expects. The result is a null dereference, an out-of-bounds read, or worse. The key point is that the range or length constraint exists somewhere (a constructor, a marker convention, a non-empty-name assumption) but the parsing path does not enforce it.

## Where it shows up
- A container class restricts ids in its constructor, but the deserializer builds the object without calling it and indexes the lookup table directly [E1](https://bugbountylibrary.com/r/h1%3A1812732.md).
- A lookup returns null for an unknown id and the caller dereferences it without a null check [E1](https://bugbountylibrary.com/r/h1%3A1812732.md).
- A fixed-size field is read at an offset derived from a marker position, with no check that enough bytes remain [E2](https://bugbountylibrary.com/r/h1%3A477344.md).
- An index expression like `buf[len - 1]` where `len` can be zero, giving `buf[-1]` [E3](https://bugbountylibrary.com/r/h1%3A115702.md).
- Parsers of metadata, manifests, search lists or config where lengths and ids come from the same untrusted input.

## How to review
For every input-derived id or index, find the check that bounds it and confirm it runs on the parsing path, not only in a constructor or a different code path. The invariant: before any table lookup or buffer access, the id is within the table's valid range and the buffer has at least the bytes the access needs. For null-returning lookups, confirm the caller handles null. For offset arithmetic, confirm the offset plus field size does not exceed the buffer length, and that length-derived indices are guarded against zero.

## Variants seen
- Out-of-range chunk id in tournament metadata causing a null-pointer read [E1](https://bugbountylibrary.com/r/h1%3A1812732.md).
- Marker at an unexpected offset causing a 4-byte heap over-read in a PHAR parser [E2](https://bugbountylibrary.com/r/h1%3A477344.md).
- Zero-length hostname causing a one-byte read before the buffer in a DNS search routine [E3](https://bugbountylibrary.com/r/h1%3A115702.md).

## Impact and severity
In the evidence these were crashes and memory disclosure: a client crash for anyone opening a menu [E1](https://bugbountylibrary.com/r/h1%3A1812732.md), a heap over-read leaking adjacent memory or crashing [E2](https://bugbountylibrary.com/r/h1%3A477344.md), and an ASAN-detected over-read crash [E3](https://bugbountylibrary.com/r/h1%3A115702.md). Severity rises when the read feeds a length or pointer used later, or when the parser runs in a privileged or shared component.

## Why fixes fail
A range check added only in the constructor does not protect the deserializer path that bypasses it [E1](https://bugbountylibrary.com/r/h1%3A1812732.md); the fix must be at the point of use.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A1812732.md
- E2: https://bugbountylibrary.com/r/h1%3A477344.md
- E3: https://bugbountylibrary.com/r/h1%3A115702.md
