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

Reply via email to