# Wire: Unauthenticated decoder crash via 32-bit length integer overflow in ByteArrayProtoReader32 (incomplete fix of CVE-2026-45799)

Wire's Kotlin ByteArrayProtoReader32 accepted a non-negative varint length of 2147483647, overflowing pos+length into a negative limit and throwing unchecked exceptions instead of decode errors.

- Payout: Research
- Severity: high
- Program: Wire
- Found by: thientd, gladiator9797
- Disclosed: 2026-09-17
- CVE: CVE-2026-63126
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-9rm7-3qhh-h2mc
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-9rm7-3qhh-h2mc
- Tags: area:oss domain:oss impact:dos kind:research platform:ghsa sev:high tech:java technique:incomplete-fix technique:regression technique:source-review vuln:dos vuln:memory-corruption

**Target:** Protobuf decoder runtime (Kotlin ByteArrayProtoReader32, Swift ReadBuffer/ProtoReader)
**Root cause:** internalNextLengthDelimited() read an untrusted varint into an Int and only rejected negative values; pos + length overflowed signed 32-bit, producing a negative limit that bypassed the `limit > pushedLimit` guard. Cursor/pointer advancement happened before bounds validation.
**Steps:**
1. Send `0A FF FF FF FF 07` (field 1 length-delimited, varint length 2147483647) to `Person.ADAPTER.decode(byteArray)`
2. Observe pre-fix `IllegalArgumentException: startIndex: 6 > endIndex: -2147483643`
3. Variant `1A FF FF FF FF 07` (unknown field 3) yields `ArrayIndexOutOfBoundsException`
4. Skipped-group variant `0B 0A FF FF FF FF 07 0C` also triggers the overflow
5. Fixed behavior: IOException/EOFException
**How found:** Auditing for the same bug class as the negative-length skipped-group fix (CVE-2026-45799); noticed the check only rejected negative lengths, so a positive length like 2147483647 still overflows pos+length into a negative limit that evades the `limit > pushedLimit` guard.
**Exploitation:** Attacker supplies a single short malformed protobuf payload to any endpoint decoding attacker-controlled bytes with Wire; unchecked RuntimeException escapes the decode boundary and can crash request handling or the process. Availability impact only.
**Insight:** When a parser validates `length < 0` but then computes `pos + length`, test INT_MAX: the sum wraps negative and can slip past upper-bound guards that only compare against a positive pushedLimit. Also check that scalar reads respect the current length-delimited message limit, not just the underlying buffer size.

