Hi,

On Sat, 2021-05-01 at 17:59 +0200, Mark Wielaard wrote:
> There is __libdw_form_val_compute_len which already handles
> DW_FORM_indirect:
> 
>     case DW_FORM_indirect:
>       get_uleb128 (u128, valp, endp);
>       // XXX Is this really correct?
>       result = __libdw_form_val_len (cu, u128, valp);
>       if (result != (size_t) -1)
>         result += valp - startp;
>       else
>         return (size_t) -1;
>       break;
> 
> I believe the XXX question can be answered with: Yes, the result is the
> size of the actual FORM data plus the size of the uleb128 encoding that
> FORM (which is valp - startp). And it probably should check like your
> code does that valp != DW_FORM_indirect && valp !=
> DW_FORM_implicit_const. I'll sent a patch to do that.

Patch attached.

Cheers,

Mark
From 73d0a32b44aa9bc641f0d5f0d79ee626d1ad2e4a Mon Sep 17 00:00:00 2001
From: Mark Wielaard <m...@klomp.org>
Date: Sat, 1 May 2021 18:00:49 +0200
Subject: [PATCH] libdw: Document and handle DW_FORM_indirect in
 __libdw_form_val_compute_len

Update the documentation in __libdw_form_val_compute_len for handling
DW_FORM_indirect and make sure the indirect form isn't DW_FORM_indirect
itself or DW_FORM_implicit_const.

Signed-off-by: Mark Wielaard <m...@klomp.org>
---
 libdw/ChangeLog    | 5 +++++
 libdw/libdw_form.c | 6 +++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index e3e467ee..aa3e5ee2 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2021-05-01  Mark Wielaard  <m...@klomp.org>
+
+	* libdw_form.c (__libdw_form_val_compute_len): Check indirect
+	form is not DW_FORM_indirect or DW_FORM_implicit_const.
+
 2021-04-23  Omar Sandoval  <osan...@fb.com>
 
 	* dwarf_child.c (__libdw_find_attr): Handle DW_FORM_indirect.
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
index 584c8467..c83dfb39 100644
--- a/libdw/libdw_form.c
+++ b/libdw/libdw_form.c
@@ -116,8 +116,12 @@ __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
       break;
 
     case DW_FORM_indirect:
+      /* The amount of data to skip in the DIE is the size of the actual
+	 FORM data (which is __libdw_form_val_len) plus the size of the
+	 uleb128 encoding that FORM (which is valp - startp).  */
       get_uleb128 (u128, valp, endp);
-      // XXX Is this really correct?
+      if (*valp == DW_FORM_indirect || *valp == DW_FORM_implicit_const)
+	return (size_t) -1;
       result = __libdw_form_val_len (cu, u128, valp);
       if (result != (size_t) -1)
 	result += valp - startp;
-- 
2.18.4

Reply via email to