On Thu, May 31, 2018 at 01:02:44PM +0200, Mark Wielaard wrote:
> Add explicit test in get-units-invalid for dwarf_cuoffset and
> dwarf_dieoffset.

And that test caught another bug on 32bit systems!

>  Dwarf_Off
>  dwarf_dieoffset (Dwarf_Die *die)
>  {
> -  return (die == NULL
> +  return ((die == NULL || die->cu == NULL)
>         ? ~0ul
>         : (Dwarf_Off) (die->addr - die->cu->startp + die->cu->start));

Note that ~0ul != (Dwarf_Off) -1 on 32bit systems.
So error detection was always broken.

The reason we didn't notice before was because we had a similar bug
in eu-readelf...

I am checking in the attached patch which fixes both.
>From aa02fb9028abcadaa18440b86b1ed085e029956c Mon Sep 17 00:00:00 2001
From: Mark Wielaard <m...@klomp.org>
Date: Thu, 31 May 2018 13:01:39 +0200
Subject: [PATCH] libdw: Don't crash on invalid die in dwarf_dieoffset.

Add explicit test in get-units-invalid for dwarf_cuoffset and
dwarf_dieoffset. Make sure dwarf_dieoffset returns (Dwarf_Off) -1
on failure.

Signed-off-by: Mark Wielaard <m...@klomp.org>
---
 libdw/ChangeLog           |  5 +++++
 libdw/dwarf_dieoffset.c   |  4 ++--
 src/ChangeLog             |  4 ++++
 src/readelf.c             |  2 +-
 tests/ChangeLog           |  5 +++++
 tests/get-units-invalid.c | 14 +++++++++++++-
 6 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 5a33d9c..38b45ba 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-31  Mark Wielaard  <m...@klomp.org>
+
+	* dwarf_dieoffset.c: Check die->cu != NULL. Return -1, not ~0ul
+	on failure.
+
 2018-05-29  Mark Wielaard  <m...@klomp.org>
 
 	* dwarf_cuoffset.c (dwarf_cuoffset): Check die->cu is not NULL.
diff --git a/libdw/dwarf_dieoffset.c b/libdw/dwarf_dieoffset.c
index 8028f6d..3a8e2cb 100644
--- a/libdw/dwarf_dieoffset.c
+++ b/libdw/dwarf_dieoffset.c
@@ -38,8 +38,8 @@
 Dwarf_Off
 dwarf_dieoffset (Dwarf_Die *die)
 {
-  return (die == NULL
-	  ? ~0ul
+  return ((die == NULL || die->cu == NULL)
+	  ? (Dwarf_Off) -1
 	  : (Dwarf_Off) (die->addr - die->cu->startp + die->cu->start));
 }
 INTDEF(dwarf_dieoffset)
diff --git a/src/ChangeLog b/src/ChangeLog
index f424fb7..03ed5aa 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2018-05-31  Mark Wielaard  <m...@klomp.org>
+
+	* readelf.c (print_debug_units): Check offset against -1 not ~0ul.
+
 2018-05-29  Mark Wielaard  <m...@klomp.org>
 
 	* readelf.c (print_debug_loc_section): Handle GNU DebugFission list
diff --git a/src/readelf.c b/src/readelf.c
index 2ccbea5..470a94e 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -7588,7 +7588,7 @@ print_debug_units (Dwfl_Module *dwflmod,
   do
     {
       Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
-      if (unlikely (offset == ~0ul))
+      if (unlikely (offset == (Dwarf_Off) -1))
 	{
 	  if (!silent)
 	    error (0, 0, gettext ("cannot get DIE offset: %s"),
diff --git a/tests/ChangeLog b/tests/ChangeLog
index b656bee..521df52 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-31  Mark Wielaard  <m...@klomp.org>
+
+	* get-units-invalid.c (main): Check dwarf_cuoffset and
+	dwarf_dieoffset.
+
 2018-05-29  Mark Wielaard  <m...@klomp.org>
 
 	* dwarf-die-addr-die.c (check_dbg): Also check subdies, split or
diff --git a/tests/get-units-invalid.c b/tests/get-units-invalid.c
index 58b32c0..ba0f818 100644
--- a/tests/get-units-invalid.c
+++ b/tests/get-units-invalid.c
@@ -83,7 +83,19 @@ main (int argc, char *argv[])
 	      if (dwarf_ranges (&subdie, 0, &base, &start, &end) != -1)
 		{
 		  printf ("Should NOT have a ranges: %s\n",
-			  dwarf_diename (&result));
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      if (dwarf_cuoffset (&subdie) != (Dwarf_Off) -1)
+		{
+		  printf ("Should NOT have a cuoffset: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      if (dwarf_dieoffset (&subdie) != (Dwarf_Off) -1)
+		{
+		  printf ("Should NOT have a die offset: %s\n",
+			  dwarf_diename (&subdie));
 		  return -1;
 		}
 	    }
-- 
1.8.3.1

Reply via email to