# Arbitrary heap overread in strscan on 32 bit Ruby, patch included

Integer overflow in strscan's extract_beg_len on 32-bit Ruby lets peek() read past the string buffer, leaking heap memory including binary contents.

- Payout: hidden
- Severity: low
- Program: Ruby
- Found by: guido
- Disclosed: 2016-11-17
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/166661
- Library page: https://bugbountylibrary.com/r/h1%3A166661
- Tags: area:oss domain:oss impact:data-leak kind:bounty platform:hackerone sev:low tech:ruby technique:source-review vuln:info-disclosure vuln:memory-corruption

**Target:** strscan C extension (ext/strscan/strscan.c) on 32-bit Ruby
**Root cause:** extract_beg_len computes beg_i + len in signed long without overflow check; on 32-bit, beg_i near 0x7FFFFFFD plus len 40000 wraps negative, bypassing the S_LEN(p) bound and passing a huge/negative length to str_new.
**Steps:**
1. Build 32-bit Ruby (tested ruby-2.3.1).
2. Create a string of length 0x7FFFFFFE: `x = 'x' * 0x7FFFFFFE`.
3. Wrap in scanner: `s = StringScanner.new(x)`.
4. Set position near LONG_MAX: `s.pos = 0x7FFFFFFD`.
5. Call `t = s.peek(40000)` — beg_i + len overflows.
6. Print non-zero bytes of t and pipe through `strings` to observe leaked heap/binary data.
**How found:** Reasoned about signed integer overflow in the beg_i + len bound check in extract_beg_len, then crafted a string and position near LONG_MAX on 32-bit to trigger the wrap and observed leaked binary strings in peek output.
**Exploitation:** Any Ruby program using strscan peek on large buffers near the 32-bit long limit can leak adjacent heap memory (including binary/library contents) into the returned string; if that string is logged or transmitted, secret data exfiltrates. No attacker control required.
**Insight:** On 32-bit targets, audit C extensions for `a + b > limit` bounds checks where a and b are attacker-influenced longs; the sum can wrap negative and bypass the check. Test with positions near LONG_MAX and large lengths.

