# Null pointer derefence due to bug in codegen with negation without using value

mruby codegen pushed a stack value for unary minus even when val=0, corrupting the VM stack and causing a null-pointer dereference in ary_concat during case/when parsing.

- Payout: $10,000
- Severity: high
- Program: shopify-scripts
- Credited: haquaman
- Disclosed: 2016-12-17
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/187536
- Library page: https://bugbountylibrary.com/r/h1%3A187536
- Tags: domain:oss impact:dos kind:bounty platform:hackerone sev:high tech:ruby technique:fuzzing technique:source-review vuln:dos vuln:memory-corruption

**Target:** mruby compiler codegen (mruby-compiler/core/codegen.c) via sandboxed eval
**Root cause:** In codegen() handling of NODE_NEG, push() was called unconditionally instead of only when val is true, so a value was pushed onto the VM stack when none was expected, desynchronizing the stack and leaving a null register that ary_concat dereferences.
**Steps:**
1. Write crash.rb containing `p *case\n  when nil\n    -0\n    nil\nend`
2. Run `./dev/bin/mruby crash.rb` -> segfault
3. Debug in lldb: crash at `ary_concat+27` with rdx=0, `movl 0x18(%rdx),%ecx` dereferences null
4. Backtrace: mrb_ary_concat <- mrb_vm_exec <- mrb_top_run
5. Reproduce via `./bin/sandbox crash.rb` (mruby_engine.bundle) -> [BUG] Segmentation fault at 0x18
6. Fix: change `push();` to `if (val) push();` in codegen.c NODE_NEG branch
**How found:** Researcher fuzzed/experimented with unusual syntax combinations; the `-0` literal inside a `case/when` with splat `p *` produced a parser warning and crash, then used lldb to trace the null deref to ary_concat and identified the codegen push() imbalance.
**Exploitation:** Attacker submits crafted Ruby source to a service that evals untrusted code in the mruby sandbox (e.g. Shopify Scripts), triggering a segfault that crashes the host process; no code execution demonstrated, only DoS via null deref.
**Insight:** Unary operators on literals inside splat/case contexts can desync compiler stack bookkeeping; when a codegen branch emits a value, check whether the parent requested one (val flag) — mismatches surface as null derefs in unrelated runtime helpers.
