# Heap overflow due to off-by-one when expanding stack

Off-by-one in mruby's stack_extend cleared one extra stack slot past the reallocated region, causing a heap buffer overflow when a deeply nested ensure/yield expression expanded the stack.

- Payout: $800
- Severity: low
- Program: shopify-scripts
- Credited: titanous
- Disclosed: 2017-02-07
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/194906
- Library page: https://bugbountylibrary.com/r/h1%3A194906
- Tags: domain:oss impact:dos kind:bounty platform:hackerone sev:low tech:ruby technique:fuzzing vuln:dos vuln:memory-corruption

**Target:** mruby VM stack expansion (src/vm.c init_new_stack_space)
**Root cause:** init_new_stack_space called stack_clear with length room-keep instead of room-keep-1, so the zeroing memcpy wrote one slot (16 bytes) past the end of the newly allocated stack region.
**Steps:**
1. Build mruby with ASAN.
2. Run the provided Ruby snippet containing deeply nested `>>=`/`ensure`/`yield` expressions that force stack_extend with keep>0.
3. Observe ASAN heap-buffer-overflow WRITE of size 16 in stack_clear via init_new_stack_space at vm.c:127.
4. Apply patch changing `room - keep` to `room - keep - 1`.
**How found:** Fuzzing/random test case generation produced a crashing input; ASAN traceback pinpointed stack_clear writing past the realloc'd 4096-byte region during stack_extend.
**Insight:** When auditing VM stack-growth code, check the clear/init length against the actual allocated delta — off-by-one in `room - keep` style arithmetic writes past realloc'd regions and is trivially found by ASAN on deeply nested constructs.
