# Incorrect code generation with redo inside NODE_RESCUE.

`redo` inside a rescue clause generated a bytecode infinite loop between OP_ONERR and OP_JMP, exhausting memory in mruby.

- Payout: $100
- Severity: low
- Program: shopify-scripts
- Credited: dgaletic
- Disclosed: 2017-02-28
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/200387
- Library page: https://bugbountylibrary.com/r/h1%3A200387
- Tags: domain:oss impact:dos kind:bounty platform:hackerone sev:low tech:ruby technique:source-review vuln:dos

**Target:** mruby compiler (codegen.c) via Shopify Scripts sandbox
**Root cause:** Codegen for NODE_REDO inside NODE_RESCUE emits OP_JMP back to OP_ONERR, creating a self-loop; OP_ONERR reallocs the rescue stack each iteration, growing memory unbounded.
**Steps:**
1. Submit script `class A redo\nrescue c\nend` to the mruby engine
2. Compiler emits irep with `OP_ONERR 003` at 000 and `OP_JMP 000` at 001
3. Execution loops between the two instructions
4. OP_ONERR doubles mrb->c->rescue via realloc each pass until memory exhausted
**How found:** Noticed MRI Ruby rejects `redo` in rescue context as a syntax error; tested the same construct in mruby, observed memory exhaustion, then dumped bytecode to find the OP_ONERR/OP_JMP self-loop and traced it to codegen.c.
**Exploitation:** Attacker submits the crafted script to the sandboxed mruby engine; the bytecode self-loop drives unbounded realloc of the rescue stack, consuming all available memory. Mitigated in the Shopify sandbox by the instruction quota.
**Insight:** When a language construct is a syntax error in MRI but accepted by mruby, diff the bytecode: constructs like `redo`/`retry` in unusual scopes can emit backward jumps into setup opcodes (OP_ONERR) that have side effects like realloc, turning a compile-time gap into a runtime resource sink.
