https://sourceware.org/bugzilla/show_bug.cgi?id=34779

            Bug ID: 34779
           Summary: objdump -P data_in_code: Mach-O data-in-code dump
                    reads past its buffer when datasize is not a multiple
                    of 8
           Product: binutils
           Version: 2.47
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: i at mi11ion dot io
  Target Milestone: ---
              Host: aarch64-apple-darwin

Created attachment 17103
  --> https://sourceware.org/bugzilla/attachment.cgi?id=17103&action=edit
dice12.o: Mach-O object, LC_DATA_IN_CODE datasize 12

Environment: GNU objdump (GNU Binutils) 2.47.20260726 and 2.46.0.20260210,
Homebrew binutils on macOS 27.0 (arm64). The code is unchanged on master at
21cffe7c0955c6bdb0c14ded96939d409f3c21f0.

Reproducer: the attached dice12.o (60 bytes) is a Mach-O arm64 MH_OBJECT with
one LC_DATA_IN_CODE load command (dataoff 48, datasize 12). The 12 region bytes
are "40 20 00 00 08 00 04 00 50 20 00 00": one 8-byte data_in_code_entry
(offset 0x2040, length 8, kind 4) and 4 trailing bytes. The file ends at the
region's end.

00000000: cffa edfe 0c00 0001 0000 0000 0100 0000  ................
00000010: 0100 0000 1000 0000 0000 0000 0000 0000  ................
00000020: 2900 0000 1000 0000 3000 0000 0c00 0000  ).......0.......
00000030: 4020 0000 0800 0400 5020 0000            @ ......P ..

Command: objdump -P data_in_code dice12.o

Actual:

   offset     length kind
   0x00002040 0x0008 0x0004 4 bytes jump table
   0x00002050 0x0000 0x0000 *UNKNOWN*

Expected: the first entry alone, since 12 bytes hold one 8-byte entry
(<mach-o/loader.h>: "an array of data_in_code_entry entries"; struct
data_in_code_entry { uint32_t offset; uint16_t length; uint16_t kind; }),
optionally with a note that 4 trailing bytes remain. Apple's otool -G prints
one entry.

Analysis: dump_data_in_code in binutils/od-macho.c (line 1398) allocates
datasize bytes and loops for (p = buf; p < buf + cmd->datasize; ), reading an
8-byte entry at p. The condition checks the entry's first byte only; with
datasize 12 the second iteration reads length and kind from buf[12..15], 4
bytes past the allocation. The printed values do not come from the file:
appending aa bb cc dd to the file after the region leaves the output unchanged.
With datasize 4 the tool prints one entry from a region that holds none.

The loop should only read an entry when all 8 of its bytes are inside the
region (and could report any trailing bytes as truncated). The loop in
dump_obj_compact_unwind (line 1998, for (p = content; p < content + size; p +=
sizeof (*e))) has the same form.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to