# mrb_vformat() heap overflow could lead to code execution

Unchecked width in mruby's sprintf '%N$' format lets a crafted format string corrupt mrb_value objects, crashing and potentially enabling code execution.

- Payout: hidden
- Severity: none
- Program: Shopify
- Found by: mg36
- Disclosed: 2017-02-10
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/192318
- Library page: https://bugbountylibrary.com/r/h1%3A192318
- Tags: area:oss domain:oss impact:dos impact:rce kind:bounty platform:hackerone tech:ruby technique:source-review vuln:memory-corruption vuln:rce

**Target:** mruby interpreter sprintf/format string parser (mrb_vformat)
**Root cause:** mrb_vformat parses the number between '%' and '$' without bounds checking, and mrb_fixnum_to_str/join_ary then treats that huge index as a value, causing out-of-bounds read/write of mrb_value objects.
**Steps:**
1. Build mruby with ASan.
2. Run the script `'%A%1094861636$'%2` via mruby.
3. Observe heap-buffer-overflow in mrb_obj_respond_to / mrb_class when the oversized positional index is used.
4. Vary the number (e.g. 1094861636) to target a chosen pointer address for overwrite.
**How found:** Code review of mrb_vformat's format parsing noticed no validation of the number between '%' and '$'; crafted a minimal sprintf call with a huge positional index and confirmed with ASan/GDB that it corrupts memory.
**Exploitation:** Attacker supplies a format string with a large positional index; the unchecked number is used as an argument index, causing join_ary to read/write out of bounds. By grooming the heap and choosing the number as a target pointer address, an attacker could overwrite mrb_value objects and potentially achieve code execution.
**Insight:** In format-string implementations, positional argument indices ('%N$') are a classic unchecked-integer sink; fuzz the numeric field between '%' and '$' with huge values and watch how the index is later used as an array/argument offset.

