Hi Mark, Thanks for catching that — you were right. The previous test file's abbrev declared DW_AT_GNU_locviews rather than DW_AT_GNU_macros, so dwarf_getmacros bailed out before reaching get_table_for_offset and the opcode-0 path was never exercised. The "invalid DWARF" was coming from the missing macro attribute, not the bug.
v2 fixes the test file: the abbrev attribute now declares DW_AT_GNU_macros, so the .debug_macro opcode_operands_table is actually reached and the opcode-0 check is what triggers. The fix in dwarf_getmacros.c is unchanged from v1. Cheers, Sayed Signed-off-by: Sayed Kaif <[email protected]> --- libdw/dwarf_getmacros.c | 12 ++++++++++++ tests/Makefile.am | 2 +- tests/run-dwarf-getmacros.sh | 8 ++++++++ tests/testfile-macros-opcode0.bz2 | Bin 0 -> 164 bytes 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/testfile-macros-opcode0.bz2 diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c index d7ed7b58..bb2272ea 100644 --- a/libdw/dwarf_getmacros.c +++ b/libdw/dwarf_getmacros.c @@ -255,11 +255,23 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff, if ((flags & 0x4) != 0) { + if (readp >= endp) + goto invalid_dwarf; unsigned count = *readp++; for (unsigned i = 0; i < count; ++i) { + if (readp >= endp) + goto invalid; unsigned opcode = *readp++; + /* Opcode 0 is not allocated (and 0xff means "not stored"). + Reject it here: without this check the unsigned expression + opcode - 1 wraps to UINT_MAX for opcode == 0, and the + assignment below would write a Dwarf_Macro_Op_Proto far out + of the bounds of the op_protos[255] stack array. */ + if (opcode == 0) + goto invalid; + Dwarf_Macro_Op_Proto e; if (readp >= endp) goto invalid; diff --git a/tests/Makefile.am b/tests/Makefile.am index 8ae7d126..2881989d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -411,7 +411,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh \ testfile46.bz2 testfile47.bz2 testfile48.bz2 testfile48.debug.bz2 \ testfile49.bz2 testfile50.bz2 testfile51.bz2 \ - testfile-macros-0xff.bz2 \ + testfile-macros-0xff.bz2 testfile-macros-opcode0.bz2 \ run-readelf-macro.sh testfilemacro.bz2 testfileclangmacro.bz2 \ run-readelf-loc.sh testfileloc.bz2 \ splitdwarf4-not-split4.dwo.bz2 \ 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..cd39615855edf4ff84c572b39f8017fb451b8b15 GIT binary patch literal 164 zcmZ>Y%CIzaj8qGboW)`(!N5@Ze?k4b2OSKK0?ffI4hs7p&u3VmpujLmU_k~02;6EG znl-Dc*`ccEg0cexQ?Y+)Z_fUbr?bpEXT~gaa~5ISu~99AgJ}!LRbC+`Nx{1{Y5QY! z1NfM(KU{h2iAPhlA>)g-$=QttEEl+S4aFigY&buDPS`!sz3@rhkCqusmNTt;CUwt< QS;YBYyvWreU;@Zh00T@uK>z>% literal 0 HcmV?d00001 -- 2.52.0.windows.1
