summaryrefslogtreecommitdiffstats
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-06-28 17:53:12 +0200
committerMark Wielaard <mark@klomp.org>2018-06-29 19:43:28 +0200
commit6dd08dc77dfde80efb349bfab4df67b375f47293 (patch)
treea8c122b109e0b4f394ad2bb6d40b630751b65b93 /libdw
parentc7a83bf05734e2c20d621678d0f3214475404c55 (diff)
libdw: Recognize zero terminator to end frame table in dwarf_next_cfi.
When the length is zero this is a the zero terminator that ends the frame table. Return 1 (end of table) instead of -1 (error) in that case. We cannot update next_off and don't want to caller to try again. Add testcase for dwarf_next_cfi to show both .eh_frame and .debug_frame tables and check consistency (FDEs should point to existing CIEs). Also add a self check to make sure we can read the table from the just build elfutils binaries. Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog4
-rw-r--r--libdw/dwarf_next_cfi.c8
2 files changed, 12 insertions, 0 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 1e86e682..da7ed9d0 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2018-06-28 Mark Wielaard <mark@klomp.org>
+
+ * dwarf_next_cfi.c (dwarf_next_cfi): Check whether length is zero.
+
2018-06-27 Mark Wielaard <mark@klomp.org>
* dwarf_begin_elf.c (check_section): Allow a single .debug_frame
diff --git a/libdw/dwarf_next_cfi.c b/libdw/dwarf_next_cfi.c
index 53fc3697..fa28d99b 100644
--- a/libdw/dwarf_next_cfi.c
+++ b/libdw/dwarf_next_cfi.c
@@ -54,6 +54,7 @@ dwarf_next_cfi (const unsigned char e_ident[],
we don't know yet whether this is a 64-bit object or not. */
|| unlikely (off + 4 >= data->d_size))
{
+ done:
*next_off = (Dwarf_Off) -1l;
return 1;
}
@@ -79,6 +80,13 @@ dwarf_next_cfi (const unsigned char e_ident[],
}
length = read_8ubyte_unaligned_inc (&dw, bytes);
}
+
+ /* Not explicitly in the DWARF spec, but mentioned in the LSB exception
+ frames (.eh_frame) spec. If Length contains the value 0, then this
+ CIE shall be considered a terminator and processing shall end. */
+ if (length == 0)
+ goto done;
+
if (unlikely ((uint64_t) (limit - bytes) < length)
|| unlikely (length < offset_size + 1))
goto invalid;