Hi Sayed,
On Wed, 2026-06-17 at 14:41 +0200, Mark Wielaard wrote:
> On Wed, 2026-06-17 at 16:01 +0530, Sayed Kaif wrote:
> > libdw: A crafted .debug_macro section with opcode 0 makes (opcode - 1)
> > wrap to 0xFFFFFFFF in the unsigned array index, writing a 16-byte struct
> > past the 255-element op_protos array. Reject opcode == 0 and add the
> > missing readp >= endp checks before reading the count and opcode bytes.
> >
> > libdwfl: When rebuilding an ELF from process memory, segments_end used
> > the last PT_LOAD segment's end rather than the largest, so a later
> > smaller segment could shrink contents_size below an earlier segment's
> > start, underflowing end - start into a huge length and overflowing the
> > heap buffer. Skip any segment that starts past contents_size, matching
> > the guard already used in dwfl_segment_report_module.
>
> Nice finds. Would you mind if I split this patch in two for the two
> separate issues?
>
> So the first would be covered by:
>
> > * libdw/dwarf_getmacros.c (get_macinfo_table): Reject opcode 0,
> > add bounds checks.
> > * tests/testfile-macros-opcode0.bz2: New test input.
> > * tests/run-dwarf-getmacros.sh: Test it.
> > * tests/Makefile.am (EXTRA_DIST): Add new test file.
>
> And the second just by:
>
> > * libdwfl/elf-from-memory.c (elf_from_remote_memory): Skip
> > out-of-range segment.
So I pushed the second, but not the first yet.
> > diff --git a/tests/run-dwarf-getmacros.sh b/tests/run-dwarf-getmacros.sh
> > index 220c2426..bda6690d 100755
> > --- a/tests/run-dwarf-getmacros.sh
> > +++ b/tests/run-dwarf-getmacros.sh
> > @@ -707,6 +707,14 @@ file /home/petr/proj/elfutils/master/elfutils/x.c
> > /file
> > EOF
> >
> > +# A .debug_macro opcode_operands_table that defines opcode 0 used to make
> > +# get_table_for_offset() compute op_protos[(unsigned)0 - 1] and write far
> > +# out of bounds. It must now be rejected as invalid DWARF.
> > +testfiles testfile-macros-opcode0
> > +testrun_compare ${abs_builddir}/dwarf-getmacros testfile-macros-opcode0
> > 0xb <<\EOF
> > +invalid DWARF
> > +EOF
> > +
> > # See testfile-dwp.source.
> > testfiles testfile-dwp-5 testfile-dwp-5.dwp
> > testfiles testfile-dwp-4-strict testfile-dwp-4-strict.dwp
> > diff --git a/tests/testfile-macros-opcode0.bz2
> > b/tests/testfile-macros-opcode0.bz2
> > new file mode 100644
> > index
> > 0000000000000000000000000000000000000000..5e4cb8684065c20b00b0cbde317cf733c8e7a0e9
> > GIT binary patch
> > literal 166
> > zcmZ>Y%CIzaj8qGbRLPmZ%D_<ie?|Sf2OSKK0?ffI4hs7p&u3V`z|f$;FiBuR1_KD(
> > zY8IL`tE$<ds^@~T0|QgBe`;^e{*tG&%sXesEOc`gVcW4$Erf$<3&&MnAtp(|yESS1
> > zV|4@gn65uudF+WtQ?()Ei?+$xjRq_ixOEN1A~kF{KYmWwJ<+}JN!^c@8BCTlt$QYQ
> > S&xl#X`Cq)q)goX5$Xx(&Fh3Ol
> >
> > literal 0
> > HcmV?d00001
So this testcase doesn't actually trigger the invalid DWARF part.
That is because the test file has single CU DIE with:
DWARF section [ 1] '.debug_info' at offset 0x40:
[Offset]
Compilation unit at offset 0:
Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
[ b] compile_unit abbrev: 1
eu-readelf: DIE [b] cannot get attribute 'GNU_locviews' (sec_offset) value:
.debug_loc section missing
DWARF section [ 2] '.debug_abbrev' at offset 0x50:
[ Code]
Abbreviation section at offset 0:
[ 1] offset: 0, children: no, tag: compile_unit
attr: GNU_locviews, form: sec_offset, offset: 0
DWARF section [ 3] '.debug_macro' at offset 0x59:
Offset: 0x0
Version: 4
Flag: 0x4 (operands_table)
Offset length: 4
extension opcode table, 1 items:
[0]eu-readelf: invalid data
So that is a DW_AT_GNU_locviews and not a DW_AT_GNU_macros.
And the testcase (dwarf_getmacros) tries to follow the DW_AT_GNU_macros
to get at the correct offset in the .debug_macros.
So maybe you attached the wrong testfile?
Thanks,
Mark