This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libdw: Add get_uleb128 and get_sleb128 bounds checking.


This finally adds bounds checking to get_[us]leb128 (with two exceptions,
see below). The performance results are a little puzzling, so I hope
Josh can take a look how things are for him.

On one system, with 3.10.0-123.13.1.el7.x86_64, varlocs -k slows down:
0.160:       53.65
master:      52.24
mjw/pending: 56.35

But on another, with 3.17.4-301.fc21.x86_64, varlocs -k speeds up:
0.160:       69.41
master:      69.03
mjw/pending: 68.29

Output is the same between versions for each system.

Both get_uleb128 and get_sleb128 now take an end pointer to prevent
reading too much data. Adjust all callers to provide the end pointer.

There are still two exceptions. "Raw" dwarf_getabbrevattr and
read_encoded_valued don't have a end pointer associated yet.
They will have to be provided in the future.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdw/ChangeLog              |  35 ++++++
 libdw/cfi.c                  |  69 +++++++-----
 libdw/dwarf_child.c          |  16 ++-
 libdw/dwarf_formblock.c      |   3 +-
 libdw/dwarf_formref.c        |  22 +++-
 libdw/dwarf_formsdata.c      |  27 ++++-
 libdw/dwarf_formudata.c      |  23 +++-
 libdw/dwarf_frame_register.c |   6 +-
 libdw/dwarf_getabbrev.c      |  19 +++-
 libdw/dwarf_getabbrevattr.c  |   9 +-
 libdw/dwarf_getattrs.c       |   7 +-
 libdw/dwarf_getlocation.c    |  39 ++++---
 libdw/dwarf_getmacros.c      |   5 +-
 libdw/dwarf_getsrclines.c    |  54 ++++++---
 libdw/dwarf_hasattr.c        |  13 +--
 libdw/dwarf_next_cfi.c       |  20 +++-
 libdw/encoded-value.h        |   8 +-
 libdw/fde.c                  |   4 +-
 libdw/libdwP.h               |   2 +-
 libdw/libdw_form.c           |   8 +-
 libdw/memory-access.h        |  13 ++-
 src/ChangeLog                |  13 +++
 src/elflint.c                |   6 +-
 src/readelf.c                | 257 +++++++++++++++++++++++++------------------
 24 files changed, 433 insertions(+), 245 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 6bb326d..0543740 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,38 @@
+2014-12-14  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.c (execute_cfi): Add program bounds checks.
+	* dwarf_child.c (__libdw_find_attr): Add attrp bounds checks.
+	* dwarf_formblock.c (dwarf_formblock): Call get_uleb128 with endp.
+	* dwarf_formref.c (__libdw_formref): Add datap bounds checks.
+	* dwarf_formsdata.c (dwarf_formsdata): Likewise.
+	* dwarf_formudata.c (dwarf_formudata): Likewise.
+	* dwarf_frame_register.c (dwarf_frame_register): Call get_uleb128
+	with end of data buf.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Add abbrevp bounds checks.
+	* dwarf_getabbrevattr.c (dwarf_getabbrevattr): Assume get_uleb128
+	call gets enough data.
+	* dwarf_getattrs,c (dwarf_getattrs): Call get_uleb128 with endp.
+	* dwarf_getlocation.c (store_implicit_value): Call get_uleb128
+	with enough data.
+	(__libdw_intern_expression): Call get_uleb128/get_sleb128 with
+	end_data.
+	* dwarf_getmacros.c (get_table_for_offset): Add nforms bounds check.
+	* dwarf_getsrclines.c (read_srclines): Bounds check linep and call
+	get_uleb128 with lineendp.
+	* dwarf_hasattr.c (dwarf_hasattr): Bounds check attrp and call
+	get_uleb128 with endp.
+	* dwarf_next_cfi.c (dwarf_next_cfi): Bounds check bytes and call
+	get_uleb128/get_sleb128 with limit.
+	* encoded-value.h (read_encoded_value): Assume get_uleb128 and
+	get_sleb128 get called with enough data.
+	* fde.c (intern_fde): Call get_uleb128 with instructions_end.
+	* libdwP.h (__libdw_dieabbrev): Call get_uleb128 with die->cu->endp.
+	* libdw_form.c (__libdw_form_val_compute_len): Call get_uleb128 with
+	endp.
+	* memory-access.h (__libdw_get_uleb128): Take an extra endp.
+	Don't call get_uleb128_step if out of data.
+	(__libdw_get_sleb128): Likewise for get_sleb128_step.
+
 2014-12-12  Mark Wielaard  <mjw@redhat.com>
 
 	* libdwP.h (struct Dwarf): Add fake_loc_cu.
diff --git a/libdw/cfi.c b/libdw/cfi.c
index a146f12..632e91d 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -1,5 +1,5 @@
 /* CFI program execution.
-   Copyright (C) 2009-2010 Red Hat, Inc.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -132,12 +132,15 @@ execute_cfi (Dwarf_CFI *cache,
 	  break;
 
 	case DW_CFA_advance_loc2:
+	  cfi_assert (program + 2 <= end);
 	  operand = read_2ubyte_unaligned_inc (cache, program);
 	  goto advance_loc;
 	case DW_CFA_advance_loc4:
+	  cfi_assert (program + 4 <= end);
 	  operand = read_4ubyte_unaligned_inc (cache, program);
 	  goto advance_loc;
 	case DW_CFA_MIPS_advance_loc8:
+	  cfi_assert (program + 8 <= end);
 	  operand = read_8ubyte_unaligned_inc (cache, program);
 	  goto advance_loc;
 
@@ -153,8 +156,9 @@ execute_cfi (Dwarf_CFI *cache,
 	     switch block for the row-copying (LOC-moving) cases above.  */
 
 	case DW_CFA_def_cfa:
-	  get_uleb128 (operand, program);
-	  get_uleb128 (offset, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
 	def_cfa:
 	  fs->cfa_rule = cfa_offset;
 	  fs->cfa_val_reg = operand;
@@ -165,32 +169,33 @@ execute_cfi (Dwarf_CFI *cache,
 	  continue;
 
 	case DW_CFA_def_cfa_register:
-	  get_uleb128 (regno, program);
+	  get_uleb128 (regno, program, end);
 	  require_cfa_offset ();
 	  fs->cfa_val_reg = regno;
 	  continue;
 
 	case DW_CFA_def_cfa_sf:
-	  get_uleb128 (operand, program);
-	  get_sleb128 (sf_offset, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_sleb128 (sf_offset, program, end);
 	  offset = sf_offset * cie->data_alignment_factor;
 	  goto def_cfa;
 
 	case DW_CFA_def_cfa_offset:
-	  get_uleb128 (offset, program);
+	  get_uleb128 (offset, program, end);
 	def_cfa_offset:
 	  require_cfa_offset ();
 	  fs->cfa_val_offset = offset;
 	  continue;
 
 	case DW_CFA_def_cfa_offset_sf:
-	  get_sleb128 (sf_offset, program);
+	  get_sleb128 (sf_offset, program, end);
 	  offset = sf_offset * cie->data_alignment_factor;
 	  goto def_cfa_offset;
 
 	case DW_CFA_def_cfa_expression:
 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
-	  get_uleb128 (operand, program);
+	  get_uleb128 (operand, program, end);
 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
 	  fs->cfa_rule = cfa_expr;
 	  fs->cfa_data.expr.data = (unsigned char *) program;
@@ -199,65 +204,71 @@ execute_cfi (Dwarf_CFI *cache,
 	  continue;
 
 	case DW_CFA_undefined:
-	  get_uleb128 (regno, program);
+	  get_uleb128 (regno, program, end);
 	  register_rule (regno, undefined, 0);
 	  continue;
 
 	case DW_CFA_same_value:
-	  get_uleb128 (regno, program);
+	  get_uleb128 (regno, program, end);
 	  register_rule (regno, same_value, 0);
 	  continue;
 
 	case DW_CFA_offset_extended:
-	  get_uleb128 (operand, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
 	case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX:
-	  get_uleb128 (offset, program);
+	  get_uleb128 (offset, program, end);
 	  offset *= cie->data_alignment_factor;
 	offset_extended:
 	  register_rule (operand, offset, offset);
 	  continue;
 
 	case DW_CFA_offset_extended_sf:
-	  get_uleb128 (operand, program);
-	  get_sleb128 (sf_offset, program);
+	  get_uleb128 (operand, program, end);
+	  get_sleb128 (sf_offset, program, end);
 	offset_extended_sf:
 	  offset = sf_offset * cie->data_alignment_factor;
 	  goto offset_extended;
 
 	case DW_CFA_GNU_negative_offset_extended:
 	  /* GNU extension obsoleted by DW_CFA_offset_extended_sf.  */
-	  get_uleb128 (operand, program);
-	  get_uleb128 (offset, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
 	  sf_offset = -offset;
 	  goto offset_extended_sf;
 
 	case DW_CFA_val_offset:
-	  get_uleb128 (operand, program);
-	  get_uleb128 (offset, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
 	  offset *= cie->data_alignment_factor;
 	val_offset:
 	  register_rule (operand, val_offset, offset);
 	  continue;
 
 	case DW_CFA_val_offset_sf:
-	  get_uleb128 (operand, program);
-	  get_sleb128 (sf_offset, program);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_sleb128 (sf_offset, program, end);
 	  offset = sf_offset * cie->data_alignment_factor;
 	  goto val_offset;
 
 	case DW_CFA_register:
-	  get_uleb128 (regno, program);
-	  get_uleb128 (operand, program);
+	  get_uleb128 (regno, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (operand, program, end);
 	  register_rule (regno, register, operand);
 	  continue;
 
 	case DW_CFA_expression:
 	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
 	  assert (! abi_cfi);
-	  get_uleb128 (regno, program);
+	  get_uleb128 (regno, program, end);
 	  offset = program - (const uint8_t *) cache->data->d.d_buf;
 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
-	  get_uleb128 (operand, program);
+	  cfi_assert (program < end);
+	  get_uleb128 (operand, program, end);
 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
 	  program += operand;
 	  register_rule (regno, expression, offset);
@@ -266,17 +277,17 @@ execute_cfi (Dwarf_CFI *cache,
 	case DW_CFA_val_expression:
 	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
 	  assert (! abi_cfi);
-	  get_uleb128 (regno, program);
+	  get_uleb128 (regno, program, end);
 	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
 	  offset = program - (const uint8_t *) cache->data->d.d_buf;
-	  get_uleb128 (operand, program);
+	  get_uleb128 (operand, program, end);
 	  cfi_assert (operand <= (Dwarf_Word) (end - program));
 	  program += operand;
 	  register_rule (regno, val_expression, offset);
 	  continue;
 
 	case DW_CFA_restore_extended:
-	  get_uleb128 (operand, program);
+	  get_uleb128 (operand, program, end);
 	case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX:
 
 	  if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore))
@@ -347,7 +358,7 @@ execute_cfi (Dwarf_CFI *cache,
 
 	case DW_CFA_GNU_args_size:
 	  /* XXX is this useful for anything? */
-	  get_uleb128 (operand, program);
+	  get_uleb128 (operand, program, end);
 	  continue;
 
 	default:
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
index 96d8e23..58a438b 100644
--- a/libdw/dwarf_child.c
+++ b/libdw/dwarf_child.c
@@ -63,18 +63,16 @@ __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
   const unsigned char *attrp = abbrevp->attrp;
   while (1)
     {
-      /* Are we still in bounds?  This test needs to be refined.  */
-      if (unlikely (attrp + 1 >= endp))
+      /* Get attribute name and form.  */
+      if (unlikely (attrp >= endp))
 	goto invalid_dwarf;
-
-      /* Get attribute name and form.
-
-	 XXX We don't check whether this reads beyond the end of the
-	 section.  */
       unsigned int attr_name;
-      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_name, attrp, endp);
+
+      if (unlikely (attrp >= endp))
+	goto invalid_dwarf;
       unsigned int attr_form;
-      get_uleb128 (attr_form, attrp);
+      get_uleb128 (attr_form, attrp, endp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr_name == 0 && attr_form == 0)
diff --git a/libdw/dwarf_formblock.c b/libdw/dwarf_formblock.c
index 980bc10..3d56f22 100644
--- a/libdw/dwarf_formblock.c
+++ b/libdw/dwarf_formblock.c
@@ -73,8 +73,7 @@ dwarf_formblock (attr, return_block)
     case DW_FORM_exprloc:
       if (unlikely (endp - datap < 1))
 	goto invalid;
-      // XXX bounds check
-      get_uleb128 (return_block->length, datap);
+      get_uleb128 (return_block->length, datap, endp);
       return_block->data = (unsigned char *) datap;
       break;
 
diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c
index 86da7ea..2592437 100644
--- a/libdw/dwarf_formref.c
+++ b/libdw/dwarf_formref.c
@@ -1,5 +1,5 @@
 /* Return reference offset represented by attribute.
-   Copyright (C) 2003-2010 Red Hat, Inc.
+   Copyright (C) 2003-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -39,7 +39,8 @@ __libdw_formref (attr, return_offset)
      Dwarf_Attribute *attr;
      Dwarf_Off *return_offset;
 {
-  const unsigned char *datap;
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
 
   if (attr->valp == NULL)
     {
@@ -50,24 +51,37 @@ __libdw_formref (attr, return_offset)
   switch (attr->form)
     {
     case DW_FORM_ref1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
       *return_offset = *attr->valp;
       break;
 
     case DW_FORM_ref2:
+      if (datap + 2 > endp)
+	goto invalid;
       *return_offset = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_ref4:
+      if (datap + 4 > endp)
+	goto invalid;
       *return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_ref8:
+      if (datap + 8 > endp)
+	goto invalid;
       *return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_ref_udata:
-      datap = attr->valp;
-      get_uleb128 (*return_offset, datap);
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_offset, datap, endp);
       break;
 
     case DW_FORM_ref_addr:
diff --git a/libdw/dwarf_formsdata.c b/libdw/dwarf_formsdata.c
index 8562198..2380bf4 100644
--- a/libdw/dwarf_formsdata.c
+++ b/libdw/dwarf_formsdata.c
@@ -1,5 +1,5 @@
 /* Return signed constant represented by attribute.
-   Copyright (C) 2003, 2005 Red Hat, Inc.
+   Copyright (C) 2003, 2005, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -43,34 +43,49 @@ dwarf_formsdata (attr, return_sval)
   if (attr == NULL)
     return -1;
 
-  const unsigned char *datap;
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
 
   switch (attr->form)
     {
     case DW_FORM_data1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
       *return_sval = *attr->valp;
       break;
 
     case DW_FORM_data2:
+      if (datap + 2 > endp)
+	goto invalid;
       *return_sval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_data4:
+      if (datap + 4 > endp)
+	goto invalid;
       *return_sval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_data8:
+      if (datap + 8 > endp)
+	goto invalid;
       *return_sval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
     case DW_FORM_sdata:
-      datap = attr->valp;
-      get_sleb128 (*return_sval, datap);
+      if (datap + 1 > endp)
+	goto invalid;
+      get_sleb128 (*return_sval, datap, endp);
       break;
 
     case DW_FORM_udata:
-      datap = attr->valp;
-      get_uleb128 (*return_sval, datap);
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_sval, datap, endp);
       break;
 
     default:
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
index 41b09e1..a01ff31 100644
--- a/libdw/dwarf_formudata.c
+++ b/libdw/dwarf_formudata.c
@@ -1,5 +1,5 @@
 /* Return unsigned constant represented by attribute.
-   Copyright (C) 2003-2012 Red Hat, Inc.
+   Copyright (C) 2003-2012, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -101,15 +101,24 @@ dwarf_formudata (attr, return_uval)
   if (attr == NULL)
     return -1;
 
-  const unsigned char *datap;
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
 
   switch (attr->form)
     {
     case DW_FORM_data1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
       *return_uval = *attr->valp;
       break;
 
     case DW_FORM_data2:
+      if (datap + 2 > endp)
+	goto invalid;
       *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
       break;
 
@@ -203,13 +212,15 @@ dwarf_formudata (attr, return_uval)
       break;
 
     case DW_FORM_sdata:
-      datap = attr->valp;
-      get_sleb128 (*return_uval, datap);
+      if (datap + 1 > endp)
+	goto invalid;
+      get_sleb128 (*return_uval, datap, endp);
       break;
 
     case DW_FORM_udata:
-      datap = attr->valp;
-      get_uleb128 (*return_uval, datap);
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_uval, datap, endp);
       break;
 
     default:
diff --git a/libdw/dwarf_frame_register.c b/libdw/dwarf_frame_register.c
index 2bc5ff1..10d2fe4 100644
--- a/libdw/dwarf_frame_register.c
+++ b/libdw/dwarf_frame_register.c
@@ -1,5 +1,5 @@
 /* Get register location expression for frame.
-   Copyright (C) 2009-2010 Red Hat, Inc.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -102,7 +102,9 @@ dwarf_frame_register (fs, regno, ops_mem, ops, nops)
 
 	Dwarf_Block block;
 	const uint8_t *p = fs->cache->data->d.d_buf + reg->value;
-	get_uleb128 (block.length, p);
+	const uint8_t *end = (fs->cache->data->d.d_buf
+			      + fs->cache->data->d.d_size);
+	get_uleb128 (block.length, p, end);
 	block.data = (void *) p;
 
 	/* Parse the expression into internal form.  */
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c
index 6bb2bd7..0efde45 100644
--- a/libdw/dwarf_getabbrev.c
+++ b/libdw/dwarf_getabbrev.c
@@ -77,9 +77,11 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
      consists of two parts. The first part is an unsigned LEB128
      number representing the attribute's name. The second part is
      an unsigned LEB128 number representing the attribute's form.  */
+  const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf
+			      + dbg->sectiondata[IDX_debug_abbrev]->d_size);
   const unsigned char *start_abbrevp = abbrevp;
   unsigned int code;
-  get_uleb128 (code, abbrevp);
+  get_uleb128 (code, abbrevp, end);
 
   /* Check whether this code is already in the hash table.  */
   bool foundit = false;
@@ -100,6 +102,7 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
 	{
 	  /* A duplicate abbrev code at a different offset,
 	     that should never happen.  */
+	invalid:
 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
 	  return NULL;
 	}
@@ -113,7 +116,11 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
      overwrite its content.  This must not be a problem, since the
      content better be the same.  */
   abb->code = code;
-  get_uleb128 (abb->tag, abbrevp);
+  if (abbrevp >= end)
+    goto invalid;
+  get_uleb128 (abb->tag, abbrevp, end);
+  if (abbrevp + 1 >= end)
+    goto invalid;
   abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
   abb->attrp = (unsigned char *) abbrevp;
   abb->offset = offset;
@@ -124,8 +131,12 @@ __libdw_getabbrev (dbg, cu, offset, lengthp, result)
   unsigned int attrform;
   do
     {
-      get_uleb128 (attrname, abbrevp);
-      get_uleb128 (attrform, abbrevp);
+      if (abbrevp >= end)
+	goto invalid;
+      get_uleb128 (attrname, abbrevp, end);
+      if (abbrevp >= end)
+	goto invalid;
+      get_uleb128 (attrform, abbrevp, end);
     }
   while (attrname != 0 && attrform != 0 && ++abb->attrcnt);
 
diff --git a/libdw/dwarf_getabbrevattr.c b/libdw/dwarf_getabbrevattr.c
index 64668fe..574467c 100644
--- a/libdw/dwarf_getabbrevattr.c
+++ b/libdw/dwarf_getabbrevattr.c
@@ -1,5 +1,5 @@
 /* Get specific attribute of abbreviation.
-   Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+   Copyright (C) 2003, 2004, 2005, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -57,9 +57,10 @@ dwarf_getabbrevattr (abbrev, idx, namep, formp, offsetp)
     {
       start_attrp = attrp;
 
-      /* Attribute code and form are encoded as ULEB128 values.  */
-      get_uleb128 (name, attrp);
-      get_uleb128 (form, attrp);
+      /* Attribute code and form are encoded as ULEB128 values.i
+         XXX We have no way to bounds check.  */
+      get_uleb128 (name, attrp, attrp + len_leb128 (name));
+      get_uleb128 (form, attrp, attrp + len_leb128 (form));
 
       /* If both values are zero the index is out of range.  */
       if (name == 0 && form == 0)
diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c
index 0c54e5d..0da8b5b 100644
--- a/libdw/dwarf_getattrs.c
+++ b/libdw/dwarf_getattrs.c
@@ -75,9 +75,10 @@ dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
       Dwarf_Attribute attr;
       const unsigned char *remembered_attrp = attrp;
 
-      // XXX Fix bound checks
-      get_uleb128 (attr.code, attrp);
-      get_uleb128 (attr.form, attrp);
+      get_uleb128 (attr.code, attrp, endp);
+      if (unlikely (attrp >= endp))
+	goto invalid_dwarf;
+      get_uleb128 (attr.form, attrp, endp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr.code == 0 && attr.form == 0)
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 38e93e6..068f385 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -104,7 +104,8 @@ store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
   struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
 					   sizeof (struct loc_block_s), 1);
   const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
-  (void) __libdw_get_uleb128 (&data); // Ignored, equal to op->number.
+  // Ignored, equal to op->number.  And data length already checked.
+  (void) __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
   block->addr = op;
   block->data = (unsigned char *) data;
   block->length = op->number;
@@ -394,28 +395,28 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 	case DW_OP_piece:
 	case DW_OP_GNU_convert:
 	case DW_OP_GNU_reinterpret:
-	  /* XXX Check size.  */
-	  get_uleb128 (newloc->number, data);
+	  get_uleb128 (newloc->number, data, end_data);
 	  break;
 
 	case DW_OP_consts:
 	case DW_OP_breg0 ... DW_OP_breg31:
 	case DW_OP_fbreg:
-	  /* XXX Check size.  */
-	  get_sleb128 (newloc->number, data);
+	  get_sleb128 (newloc->number, data, end_data);
 	  break;
 
 	case DW_OP_bregx:
-	  /* XXX Check size.  */
-	  get_uleb128 (newloc->number, data);
-	  get_sleb128 (newloc->number2, data);
+	  get_uleb128 (newloc->number, data, end_data);
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_sleb128 (newloc->number2, data, end_data);
 	  break;
 
 	case DW_OP_bit_piece:
 	case DW_OP_GNU_regval_type:
-	  /* XXX Check size.  */
-	  get_uleb128 (newloc->number, data);
-	  get_uleb128 (newloc->number2, data);
+	  get_uleb128 (newloc->number, data, end_data);
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_uleb128 (newloc->number2, data, end_data);
 	  break;
 
 	case DW_OP_implicit_value:
@@ -426,8 +427,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 
 	  /* start of block inc. len.  */
 	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
-	  /* XXX Check size.  */
-	  get_uleb128 (newloc->number, data); /* Block length.  */
+	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
 	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
 	    goto invalid;
 	  data += newloc->number;		/* Skip the block.  */
@@ -438,23 +438,22 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 	  if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size,
 				       &newloc->number, IDX_debug_info, 0))
 	    return -1;
-	  /* XXX Check size.  */
-	  get_uleb128 (newloc->number2, data); /* Byte offset.  */
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
 	  break;
 
 	case DW_OP_GNU_deref_type:
-	  if (unlikely (data >= end_data))
+	  if (unlikely (data + 1 >= end_data))
 	    goto invalid;
 	  newloc->number = *data++;
-	  get_uleb128 (newloc->number2, data);
+	  get_uleb128 (newloc->number2, data, end_data);
 	  break;
 
 	case DW_OP_GNU_const_type:
 	  {
 	    size_t size;
-
-	    /* XXX Check size.  */
-	    get_uleb128 (newloc->number, data);
+	    get_uleb128 (newloc->number, data, end_data);
 	    if (unlikely (data >= end_data))
 	      goto invalid;
 
diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
index 848128e..f9f2996 100644
--- a/libdw/dwarf_getmacros.c
+++ b/libdw/dwarf_getmacros.c
@@ -215,13 +215,16 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
 	  unsigned opcode = *readp++;
 
 	  Dwarf_Macro_Op_Proto e;
-	  get_uleb128 (e.nforms, readp); // XXX checking
+	  if (readp >= endp)
+	    goto invalid;
+	  get_uleb128 (e.nforms, readp, endp);
 	  e.forms = readp;
 	  op_protos[opcode - 1] = e;
 
 	  readp += e.nforms;
 	  if (readp > endp)
 	    {
+	    invalid:
 	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
 	      return NULL;
 	    }
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 3e3ee55..d50a17d 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -240,7 +240,9 @@ read_srclines (Dwarf *dbg,
 
       /* Then the index.  */
       Dwarf_Word diridx;
-      get_uleb128 (diridx, linep);
+      if (unlikely (linep >= lineendp))
+	goto invalid_data;
+      get_uleb128 (diridx, linep, lineendp);
       if (unlikely (diridx >= ndirlist))
 	{
 	  __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
@@ -272,10 +274,14 @@ read_srclines (Dwarf *dbg,
 	}
 
       /* Next comes the modification time.  */
-      get_uleb128 (new_file->info.mtime, linep);
+      if (unlikely (linep >= lineendp))
+	goto invalid_data;
+      get_uleb128 (new_file->info.mtime, linep, lineendp);
 
       /* Finally the length of the file.  */
-      get_uleb128 (new_file->info.length, linep);
+      if (unlikely (linep >= lineendp))
+	goto invalid_data;
+      get_uleb128 (new_file->info.length, linep, lineendp);
 
       new_file->next = filelist;
       filelist = new_file;
@@ -460,11 +466,17 @@ read_srclines (Dwarf *dbg,
 		linep = endp + 1;
 
 		unsigned int diridx;
-		get_uleb128 (diridx, linep);
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (diridx, linep, lineendp);
 		Dwarf_Word mtime;
-		get_uleb128 (mtime, linep);
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (mtime, linep, lineendp);
 		Dwarf_Word filelength;
-		get_uleb128 (filelength, linep);
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (filelength, linep, lineendp);
 
 		struct filelist *new_file =
 		  (struct filelist *) alloca (sizeof (*new_file));
@@ -501,7 +513,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_uleb128 (discriminator, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (discriminator, linep, lineendp);
 	      break;
 
 	    default:
@@ -538,7 +552,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_uleb128 (u128, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
 	      advance_pc (u128);
 	      break;
 
@@ -548,7 +564,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_sleb128 (s128, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_sleb128 (s128, linep, lineendp);
 	      line += s128;
 	      break;
 
@@ -557,7 +575,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_uleb128 (u128, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
 	      file = u128;
 	      break;
 
@@ -566,7 +586,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_uleb128 (u128, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
 	      column = u128;
 	      break;
 
@@ -629,7 +651,9 @@ read_srclines (Dwarf *dbg,
 	      if (unlikely (standard_opcode_lengths[opcode] != 1))
 		goto invalid_data;
 
-	      get_uleb128 (isa, linep);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (isa, linep, lineendp);
 	      break;
 	    }
 	}
@@ -639,7 +663,11 @@ read_srclines (Dwarf *dbg,
 	     Read the parameters associated with it but then discard
 	     everything.  Read all the parameters for this opcode.  */
 	  for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
-	    get_uleb128 (u128, linep);
+	    {
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
+	    }
 
 	  /* Next round, ignore this opcode.  */
 	  continue;
diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c
index 6ed1a98..812c09b 100644
--- a/libdw/dwarf_hasattr.c
+++ b/libdw/dwarf_hasattr.c
@@ -63,17 +63,16 @@ dwarf_hasattr (die, search_name)
   while (1)
     {
       /* Are we still in bounds?  This test needs to be refined.  */
-      if (unlikely (attrp + 1 >= endp))
+      if (unlikely (attrp >= endp))
 	goto invalid_dwarf;
 
-      /* Get attribute name and form.
-
-	 XXX We don't check whether this reads beyond the end of the
-	 section.  */
+      /* Get attribute name and form.  */
       unsigned int attr_name;
-      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_name, attrp, endp);
       unsigned int attr_form;
-      get_uleb128 (attr_form, attrp);
+      if (unlikely (attrp >= endp))
+	goto invalid_dwarf;
+      get_uleb128 (attr_form, attrp, endp);
 
       /* We can stop if we found the attribute with value zero.  */
       if (attr_name == 0 || attr_form == 0)
diff --git a/libdw/dwarf_next_cfi.c b/libdw/dwarf_next_cfi.c
index 80b7dfa..b5af49e 100644
--- a/libdw/dwarf_next_cfi.c
+++ b/libdw/dwarf_next_cfi.c
@@ -1,5 +1,5 @@
 /* Advance to next CFI entry.
-   Copyright (C) 2009-2010 Red Hat, Inc.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -170,11 +170,19 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
 	  bytes += address_size;
 	}
 
-      get_uleb128 (entry->cie.code_alignment_factor, bytes);
-      get_sleb128 (entry->cie.data_alignment_factor, bytes);
+      if (bytes >= limit)
+	goto invalid;
+      get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
+
+      if (bytes >= limit)
+	goto invalid;
+      get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
+
+      if (bytes >= limit)
+	goto invalid;
 
       if (version >= 3)		/* DWARF 3+ */
-	get_uleb128 (entry->cie.return_address_register, bytes);
+	get_uleb128 (entry->cie.return_address_register, bytes, limit);
       else			/* DWARF 2 */
 	entry->cie.return_address_register = *bytes++;
 
@@ -184,7 +192,9 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
       bool sized_augmentation = *ap == 'z';
       if (sized_augmentation)
 	{
-	  get_uleb128 (entry->cie.augmentation_data_size, bytes);
+	  if (bytes >= limit)
+	    goto invalid;
+	  get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
 	  if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
 	    goto invalid;
 	  entry->cie.augmentation_data = bytes;
diff --git a/libdw/encoded-value.h b/libdw/encoded-value.h
index 4b59f62..ae9a38f 100644
--- a/libdw/encoded-value.h
+++ b/libdw/encoded-value.h
@@ -1,5 +1,5 @@
 /* DW_EH_PE_* support for libdw unwinder.
-   Copyright (C) 2009-2010 Red Hat, Inc.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -163,11 +163,13 @@ read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding, const uint8_t **p,
       break;
 
     case DW_EH_PE_uleb128:
-      get_uleb128 (value, *p);
+      // XXX we trust there is enough data.
+      get_uleb128 (value, *p, *p + len_leb128 (Dwarf_Addr));
       break;
 
     case DW_EH_PE_sleb128:
-      get_sleb128 (value, *p);
+      // XXX we trust there is enough data.
+      get_sleb128 (value, *p, *p + len_leb128 (Dwarf_Addr));
       break;
 
     default:
diff --git a/libdw/fde.c b/libdw/fde.c
index 91ce732..18a522b 100644
--- a/libdw/fde.c
+++ b/libdw/fde.c
@@ -1,5 +1,5 @@
 /* FDE reading.
-   Copyright (C) 2009-2010 Red Hat, Inc.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -97,7 +97,7 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
       /* The CIE augmentation says the FDE has a DW_FORM_block
 	 before its actual instruction stream.  */
       Dwarf_Word len;
-      get_uleb128 (len, fde->instructions);
+      get_uleb128 (len, fde->instructions, fde->instructions_end);
       if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len)
 	{
 	  free (fde);
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index eda61a9..5ab7219 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -475,7 +475,7 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
       /* Get the abbreviation code.  */
       unsigned int code;
       const unsigned char *addr = die->addr;
-      get_uleb128 (code, addr);
+      get_uleb128 (code, addr, die->cu->endp);
       if (readp != NULL)
 	*readp = addr;
 
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
index 379ede5..72e2390 100644
--- a/libdw/libdw_form.c
+++ b/libdw/libdw_form.c
@@ -86,8 +86,7 @@ __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
 
     case DW_FORM_block:
     case DW_FORM_exprloc:
-      // XXX overflow check
-      get_uleb128 (u128, valp);
+      get_uleb128 (u128, valp, endp);
       result = u128 + (valp - startp);
       break;
 
@@ -104,13 +103,12 @@ __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
     case DW_FORM_sdata:
     case DW_FORM_udata:
     case DW_FORM_ref_udata:
-      // XXX overflow check
-      get_uleb128 (u128, valp);
+      get_uleb128 (u128, valp, endp);
       result = valp - startp;
       break;
 
     case DW_FORM_indirect:
-      get_uleb128 (u128, valp);
+      get_uleb128 (u128, valp, endp);
       // XXX Is this really correct?
       result = __libdw_form_val_len (cu, u128, valp);
       if (result != (size_t) -1)
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
index 6a4ce88..8226d00 100644
--- a/libdw/memory-access.h
+++ b/libdw/memory-access.h
@@ -48,20 +48,21 @@
   } while (0)
 
 static inline uint64_t
-__libdw_get_uleb128 (const unsigned char **addrp)
+__libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
 {
   uint64_t acc = 0;
   /* Unroll the first step to help the compiler optimize
      for the common single-byte case.  */
   get_uleb128_step (acc, *addrp, 0);
-  for (unsigned int i = 1; i < len_leb128 (acc); ++i)
+  for (unsigned int i = 1; i < len_leb128 (acc) && *addrp < end; ++i)
     get_uleb128_step (acc, *addrp, i);
   /* Other implementations set VALUE to UINT_MAX in this
      case.  So we better do this as well.  */
   return UINT64_MAX;
 }
 
-#define get_uleb128(var, addr) ((var) = __libdw_get_uleb128 (&(addr)))
+/* Note, addr needs to me smaller than end. */
+#define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
 
 /* The signed case is similar, but we sign-extend the result.  */
 
@@ -78,18 +79,18 @@ __libdw_get_uleb128 (const unsigned char **addrp)
   } while (0)
 
 static inline int64_t
-__libdw_get_sleb128 (const unsigned char **addrp)
+__libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
 {
   int64_t acc = 0;
   /* Unrolling 0 like uleb128 didn't prove to benefit optimization.  */
-  for (unsigned int i = 0; i < len_leb128 (acc); ++i)
+  for (unsigned int i = 0; i < len_leb128 (acc) && *addrp < end; ++i)
     get_sleb128_step (acc, *addrp, i);
   /* Other implementations set VALUE to INT_MAX in this
      case.  So we better do this as well.  */
   return INT64_MAX;
 }
 
-#define get_sleb128(var, addr) ((var) = __libdw_get_sleb128 (&(addr)))
+#define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end))
 
 
 /* We use simple memory access functions in case the hardware allows it.
diff --git a/src/ChangeLog b/src/ChangeLog
index 141b31f..a4f42e4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
+2014-12-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_attributes): Call get_uleb128 with end pointer.
+	* readelf.c (print_attributes): Likewise.
+	(print_ops): Likewise and also for get_sleb128.
+	(print_cfa_program): Likewise and add more readp bounds checks.
+	(read_encoded): Likewise.
+	(print_debug_frame_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+	(print_debug_exception_table): Likewise.
+
 2014-12-11  Mark Wielaard  <mjw@redhat.com>
 
 	* readelf.c (print_debug_exception_table): Check TType base offset
diff --git a/src/elflint.c b/src/elflint.c
index fbc78ed..7e73253 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3266,7 +3266,7 @@ section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
 	    unsigned const char *chunk = q;
 
 	    unsigned int subsection_tag;
-	    get_uleb128 (subsection_tag, q);
+	    get_uleb128 (subsection_tag, q, p);
 
 	    if (q >= p)
 	      {
@@ -3321,13 +3321,13 @@ section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
 		while (chunk < q)
 		  {
 		    unsigned int tag;
-		    get_uleb128 (tag, chunk);
+		    get_uleb128 (tag, chunk, q);
 
 		    uint64_t value = 0;
 		    const unsigned char *r = chunk;
 		    if (tag == 32 || (tag & 1) == 0)
 		      {
-			get_uleb128 (value, r);
+			get_uleb128 (value, r, q);
 			if (r > q)
 			  {
 			    ERROR (gettext ("\
diff --git a/src/readelf.c b/src/readelf.c
index b62e778..51ce020 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3368,7 +3368,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 		const unsigned char *const sub = q;
 
 		unsigned int subsection_tag;
-		get_uleb128 (subsection_tag, q);
+		get_uleb128 (subsection_tag, q, p);
 		if (unlikely (q >= p))
 		  break;
 
@@ -3405,7 +3405,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 		    while (r < q)
 		      {
 			unsigned int tag;
-			get_uleb128 (tag, r);
+			get_uleb128 (tag, r, q);
 			if (unlikely (r >= q))
 			  break;
 
@@ -3422,7 +3422,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 			if (tag == 32 || (tag & 1) == 0
 			    || (! gnu_vendor && (tag > 5 && tag < 32)))
 			  {
-			    get_uleb128 (value, r);
+			    get_uleb128 (value, r, q);
 			    if (r > q)
 			      break;
 			  }
@@ -4116,7 +4116,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  const unsigned char *start = data;
 	  uint64_t uleb;
 	  NEED (1);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  get_uleb128 (uleb, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
 		  indent, "", (uintmax_t) offset, op_name, uleb);
 	  CONSUME (data - start);
@@ -4126,9 +4126,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_bit_piece:
 	  start = data;
 	  uint64_t uleb2;
-	  NEED (2);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
-	  get_uleb128 (uleb2, data); /* XXX check overrun */
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_uleb128 (uleb2, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
 		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
 	  CONSUME (data - start);
@@ -4141,7 +4142,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  start = data;
 	  int64_t sleb;
 	  NEED (1);
-	  get_sleb128 (sleb, data); /* XXX check overrun */
+	  get_sleb128 (sleb, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
 		  indent, "", (uintmax_t) offset, op_name, sleb);
 	  CONSUME (data - start);
@@ -4150,9 +4151,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
 	case DW_OP_bregx:
 	  start = data;
-	  NEED (2);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
-	  get_sleb128 (sleb, data); /* XXX check overrun */
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_sleb128 (sleb, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
 		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
 	  CONSUME (data - start);
@@ -4191,7 +4193,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	case DW_OP_implicit_value:
 	  start = data;
 	  NEED (1);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  get_uleb128 (uleb, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s: ",
 		  indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
@@ -4216,7 +4218,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	    }
 	  data += ref_size;
 	  /* Byte offset operand.  */
-	  get_sleb128 (sleb, data); /* XXX check overrun */
+	  NEED (1);
+	  get_sleb128 (sleb, data, data + len);
 
 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
 		  indent, "", (intmax_t) offset,
@@ -4229,7 +4232,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  /* Size plus expression block.  */
 	  start = data;
 	  NEED (1);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  get_uleb128 (uleb, data, data + len);
 	  printf ("%*s[%4" PRIuMAX "] %s:\n",
 		  indent, "", (uintmax_t) offset, op_name);
 	  NEED (uleb);
@@ -4244,10 +4247,11 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
 	     unsigned size plus block.  */
 	  start = data;
-	  NEED (2);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    uleb += cu->start;
+	  NEED (1);
 	  uint8_t usize = *(uint8_t *) data++;
 	  NEED (usize);
 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ",
@@ -4262,9 +4266,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  /* uleb128 register number, uleb128 CU relative
 	     DW_TAG_base_type DIE offset.  */
 	  start = data;
-	  NEED (2);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
-	  get_uleb128 (uleb2, data); /* XXX check overrun */
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_uleb128 (uleb2, data, data + len);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    uleb2 += cu->start;
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
@@ -4277,9 +4282,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  /* 1-byte unsigned size of value, uleb128 CU relative
 	     DW_TAG_base_type DIE offset.  */
 	  start = data;
-	  NEED (2);
+	  NEED (1);
 	  usize = *(uint8_t *) data++;
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
 	  if (! print_unresolved_addresses && cu != NULL)
 	    uleb += cu->start;
 	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
@@ -4295,7 +4301,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	     for conversion to untyped.  */
 	  start = data;
 	  NEED (1);
-	  get_uleb128 (uleb, data); /* XXX check overrun */
+	  get_uleb128 (uleb, data, data + len);
 	  if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
 	    uleb += cu->start;
 	  printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n",
@@ -4965,8 +4971,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     nop");
 	    break;
 	  case DW_CFA_set_loc:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    op1 += vma_base;
 	    printf ("     set_loc %" PRIu64 "\n", op1 * code_align);
 	    break;
@@ -4976,43 +4981,46 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    ++readp;
 	    break;
 	  case DW_CFA_advance_loc2:
+	    if ((uint64_t) (endp - readp) < 2)
+	      goto invalid;
 	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
 	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
 		    op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_advance_loc4:
+	    if ((uint64_t) (endp - readp) < 4)
+	      goto invalid;
 	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
 	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
 		    op1, pc += op1 * code_align);
 	    break;
 	  case DW_CFA_offset_extended:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
 	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
 		    "\n",
 		    op1, regname (op1), op2 * data_align);
 	    break;
 	  case DW_CFA_restore_extended:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
 		    op1, regname (op1));
 	    break;
 	  case DW_CFA_undefined:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
 	    break;
 	  case DW_CFA_same_value:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
 	    break;
 	  case DW_CFA_register:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
 	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
 		    op1, regname (op1), op2, regname (op2));
 	    break;
@@ -5023,26 +5031,24 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     restore_state");
 	    break;
 	  case DW_CFA_def_cfa:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
 	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
 		    op1, regname (op1), op2);
 	    break;
 	  case DW_CFA_def_cfa_register:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
 		    op1, regname (op1));
 	    break;
 	  case DW_CFA_def_cfa_offset:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
 	    break;
 	  case DW_CFA_def_cfa_expression:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);	/* Length of DW_FORM_block.  */
+	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
 	    if ((uint64_t) (endp - readp) < op1)
 	      {
@@ -5055,9 +5061,10 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    readp += op1;
 	    break;
 	  case DW_CFA_expression:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     expression r%" PRIu64 " (%s) \n",
 		    op1, regname (op1));
 	    if ((uint64_t) (endp - readp) < op2)
@@ -5067,43 +5074,49 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    readp += op2;
 	    break;
 	  case DW_CFA_offset_extended_sf:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_sleb128 (sop2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
 	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
 		    PRId64 "\n",
 		    op1, regname (op1), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_sf:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_sleb128 (sop2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
 	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
 		    op1, regname (op1), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_offset_sf:
-	    // XXX overflow check
-	    get_sleb128 (sop1, readp);
+	    get_sleb128 (sop1, readp, endp);
 	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
 	    break;
 	  case DW_CFA_val_offset:
 	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
 	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
 		    op1, op2 * data_align);
 	    break;
 	  case DW_CFA_val_offset_sf:
 	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_sleb128 (sop2, readp);
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
 	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
 		    op1, sop2 * data_align);
 	    break;
 	  case DW_CFA_val_expression:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
-	    get_uleb128 (op2, readp);	/* Length of DW_FORM_block.  */
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     val_expression r%" PRIu64 " (%s)\n",
 		    op1, regname (op1));
 	    if ((uint64_t) (endp - readp) < op2)
@@ -5113,6 +5126,8 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    readp += op2;
 	    break;
 	  case DW_CFA_MIPS_advance_loc8:
+	    if ((uint64_t) (endp - readp) < 8)
+	      goto invalid;
 	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
 	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
 		    op1, pc += op1 * code_align);
@@ -5121,8 +5136,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    puts ("     GNU_window_save");
 	    break;
 	  case DW_CFA_GNU_args_size:
-	    // XXX overflow check
-	    get_uleb128 (op1, readp);
+	    get_uleb128 (op1, readp, endp);
 	    printf ("     args_size %" PRIu64 "\n", op1);
 	    break;
 	  default:
@@ -5135,8 +5149,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
       else if (opcode < DW_CFA_restore)
 	{
 	  uint64_t offset;
-	  // XXX overflow check
-	  get_uleb128 (offset, readp);
+	  get_uleb128 (offset, readp, endp);
 	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
 		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
 	}
@@ -5275,12 +5288,10 @@ read_encoded (unsigned int encoding, const unsigned char *readp,
   switch (encoding & 0xf)
     {
     case DW_EH_PE_uleb128:
-      // XXX buffer overrun check
-      get_uleb128 (*res, readp);
+      get_uleb128 (*res, readp, endp);
       break;
     case DW_EH_PE_sleb128:
-      // XXX buffer overrun check
-      get_sleb128 (*res, readp);
+      get_sleb128 (*res, readp, endp);
       break;
     case DW_EH_PE_udata2:
       if (readp + 2 > endp)
@@ -5453,21 +5464,24 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      segment_size = *readp++;
 	    }
 
-	  // XXX Check overflow
-	  get_uleb128 (code_alignment_factor, readp);
-	  // XXX Check overflow
-	  get_sleb128 (data_alignment_factor, readp);
+	  if (cieend - readp < 1)
+	    goto invalid_data;
+	  get_uleb128 (code_alignment_factor, readp, cieend);
+	  if (cieend - readp < 1)
+	    goto invalid_data;
+	  get_sleb128 (data_alignment_factor, readp, cieend);
 
 	  /* In some variant for unwind data there is another field.  */
 	  if (strcmp (augmentation, "eh") == 0)
 	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
 
 	  unsigned int return_address_register;
+	  if (cieend - readp < 1)
+	    goto invalid_data;
 	  if (unlikely (version == 1))
 	    return_address_register = *readp++;
 	  else
-	    // XXX Check overflow
-	    get_uleb128 (return_address_register, readp);
+	    get_uleb128 (return_address_register, readp, cieend);
 
 	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
 		  "   CIE_id:                   %" PRIu64 "\n"
@@ -5488,7 +5502,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	  if (augmentation[0] == 'z')
 	    {
 	      unsigned int augmentationlen;
-	      get_uleb128 (augmentationlen, readp);
+	      get_uleb128 (augmentationlen, readp, cieend);
 
 	      if (augmentationlen > (size_t) (cieend - readp))
 		{
@@ -5641,9 +5655,11 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	  if (cie->augmentation[0] == 'z')
 	    {
 	      unsigned int augmentationlen;
-	      get_uleb128 (augmentationlen, readp);
+	      if (cieend - readp < 1)
+		goto invalid_data;
+	      get_uleb128 (augmentationlen, readp, cieend);
 
-	      if (augmentationlen > (size_t) (dataend - readp))
+	      if (augmentationlen > (size_t) (cieend - readp))
 		{
 		  error (0, 0, gettext ("invalid augmentation length"));
 		  readp = cieend;
@@ -6443,15 +6459,21 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 	  /* Then the index.  */
 	  unsigned int diridx;
-	  get_uleb128 (diridx, linep);
+	  if (lineendp - linep < 1)
+	    goto invalid_unit;
+	  get_uleb128 (diridx, linep, lineendp);
 
 	  /* Next comes the modification time.  */
 	  unsigned int mtime;
-	  get_uleb128 (mtime, linep);
+	  if (lineendp - linep < 1)
+	    goto invalid_unit;
+	  get_uleb128 (mtime, linep, lineendp);
 
 	  /* Finally the length of the file.  */
 	  unsigned int fsize;
-	  get_uleb128 (fsize, linep);
+	  if (lineendp - linep < 1)
+	    goto invalid_unit;
+	  get_uleb128 (fsize, linep, lineendp);
 
 	  printf (" %-5u %-5u %-9u %-9u %s\n",
 		  cnt, diridx, mtime, fsize, fname);
@@ -6608,11 +6630,17 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		    linep = endp + 1;
 
 		    unsigned int diridx;
-		    get_uleb128 (diridx, linep);
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (diridx, linep, lineendp);
 		    Dwarf_Word mtime;
-		    get_uleb128 (mtime, linep);
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (mtime, linep, lineendp);
 		    Dwarf_Word filelength;
-		    get_uleb128 (filelength, linep);
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (filelength, linep, lineendp);
 
 		    printf (gettext ("\
  define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
@@ -6626,7 +6654,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
 		    goto invalid_unit;
 
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  printf (gettext (" set discriminator to %u\n"), u128);
 		  break;
 
@@ -6650,7 +6678,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		case DW_LNS_advance_pc:
 		  /* Takes one uleb128 parameter which is added to the
 		     address.  */
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  advance_pc (u128);
 		  {
 		    char *a = format_dwarf_addr (dwflmod, 0, address, address);
@@ -6668,7 +6696,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		case DW_LNS_advance_line:
 		  /* Takes one sleb128 parameter which is added to the
 		     line.  */
-		  get_sleb128 (s128, linep);
+		  get_sleb128 (s128, linep, lineendp);
 		  line += s128;
 		  printf (gettext ("\
  advance line by constant %d to %" PRId64 "\n"),
@@ -6677,7 +6705,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 		case DW_LNS_set_file:
 		  /* Takes one uleb128 parameter which is stored in file.  */
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  printf (gettext (" set file to %" PRIu64 "\n"),
 			  (uint64_t) u128);
 		  break;
@@ -6687,7 +6715,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
 		    goto invalid_unit;
 
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  printf (gettext (" set column to %" PRIu64 "\n"),
 			  (uint64_t) u128);
 		  break;
@@ -6758,7 +6786,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  if (unlikely (standard_opcode_lengths[opcode] != 1))
 		    goto invalid_unit;
 
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  printf (gettext (" set isa to %u\n"), u128);
 		  break;
 		}
@@ -6774,7 +6802,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		      standard_opcode_lengths[opcode]);
 	      for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
 		{
-		  get_uleb128 (u128, linep);
+		  get_uleb128 (u128, linep, lineendp);
 		  if (n != standard_opcode_lengths[opcode])
 		    putc_unlocked (',', stdout);
 		  printf (" %u", u128);
@@ -7010,7 +7038,7 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      For the latter
 		number, string.
 	      We can treat these cases together.  */
-	  get_uleb128 (u128, readp);
+	  get_uleb128 (u128, readp, readendp);
 
 	  endp = memchr (readp, '\0', readendp - readp);
 	  if (unlikely (endp == NULL))
@@ -7035,8 +7063,15 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
 	case DW_MACINFO_start_file:
 	  /* The two parameters are line and file index, in this order.  */
-	  get_uleb128 (u128, readp);
-	  get_uleb128 (u128_2, readp);
+	  get_uleb128 (u128, readp, readendp);
+	  if (readendp - readp < 1)
+	    {
+	      printf (gettext ("\
+%*s*** missing DW_MACINFO_start_file argument at end of section"),
+		      level, "");
+	      return;
+	    }
+	  get_uleb128 (u128_2, readp, readendp);
 
 	  /* Find the CU DIE for this file.  */
 	  size_t macoff = readp - (const unsigned char *) data->d_buf;
@@ -7247,8 +7282,10 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
           switch (opcode)
             {
             case DW_MACRO_GNU_start_file:
-	      get_uleb128 (u128, readp);
-	      get_uleb128 (u128_2, readp);
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp >= readendp)
+		goto invalid_data;
+	      get_uleb128 (u128_2, readp, readendp);
 
 	      /* Find the CU DIE that matches this line offset.  */
 	      const char *fname = "???";
@@ -7280,7 +7317,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      break;
 
 	    case DW_MACRO_GNU_define:
-	      get_uleb128 (u128, readp);
+	      get_uleb128 (u128, readp, readendp);
 	      endp = memchr (readp, '\0', readendp - readp);
 	      if (endp == NULL)
 		goto invalid_data;
@@ -7290,7 +7327,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      break;
 
 	    case DW_MACRO_GNU_undef:
-	      get_uleb128 (u128, readp);
+	      get_uleb128 (u128, readp, readendp);
 	      endp = memchr (readp, '\0', readendp - readp);
 	      if (endp == NULL)
 		goto invalid_data;
@@ -7300,7 +7337,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      break;
 
 	    case DW_MACRO_GNU_define_indirect:
-	      get_uleb128 (u128, readp);
+	      get_uleb128 (u128, readp, readendp);
 	      if (readp + offset_len > readendp)
 		goto invalid_data;
 	      if (offset_len == 8)
@@ -7312,7 +7349,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 	      break;
 
 	    case DW_MACRO_GNU_undef_indirect:
-	      get_uleb128 (u128, readp);
+	      get_uleb128 (u128, readp, readendp);
 	      if (readp + offset_len > readendp)
 		goto invalid_data;
 	      if (offset_len == 8)
@@ -7382,17 +7419,17 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 		      break;
 
 		    case DW_FORM_sdata:
-		      get_sleb128 (val, readp);
+		      get_sleb128 (val, readp, readendp);
 		      printf (" %" PRIx64, val);
 		      break;
 
 		    case DW_FORM_udata:
-		      get_uleb128 (val, readp);
+		      get_uleb128 (val, readp, readendp);
 		      printf (" %" PRIx64, val);
 		      break;
 
 		    case DW_FORM_block:
-		      get_uleb128 (val, readp);
+		      get_uleb128 (val, readp, readendp);
 		      printf (" block[%" PRIu64 "]", val);
 		      if (readp + val > readendp)
 			goto invalid_data;
@@ -7708,7 +7745,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   if (ttype_encoding != DW_EH_PE_omit)
     {
       unsigned int ttype_base_offset;
-      get_uleb128 (ttype_base_offset, readp);
+      get_uleb128 (ttype_base_offset, readp, dataend);
       printf (" TType base offset:   %#x\n", ttype_base_offset);
       if ((size_t) (dataend - readp) > ttype_base_offset)
         ttype_base = readp + ttype_base_offset;
@@ -7720,7 +7757,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
   printf (gettext (" Call site encoding:  %#x "), call_site_encoding);
   print_encoding_base ("", call_site_encoding);
   unsigned int call_site_table_len;
-  get_uleb128 (call_site_table_len, readp);
+  get_uleb128 (call_site_table_len, readp, dataend);
 
   const unsigned char *const action_table = readp + call_site_table_len;
   if (unlikely (action_table > dataend))
@@ -7742,7 +7779,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
       readp = read_encoded (call_site_encoding, readp, dataend,
 			    &landing_pad, dbg);
       unsigned int action;
-      get_uleb128 (action, readp);
+      get_uleb128 (action, readp, dataend);
       max_action = MAX (action, max_action);
       printf (gettext (" [%4u] Call site start:   %#" PRIx64 "\n"
 		       "        Call site length:  %" PRIu64 "\n"
@@ -7771,11 +7808,11 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
       do
 	{
 	  int ar_filter;
-	  get_sleb128 (ar_filter, readp);
+	  get_sleb128 (ar_filter, readp, action_table_end);
 	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
 	    max_ar_filter = ar_filter;
 	  int ar_disp;
-	  get_sleb128 (ar_disp, readp);
+	  get_sleb128 (ar_disp, readp, action_table_end);
 
 	  printf (" [%4u] ar_filter:  % d\n"
 		  "        ar_disp:    % -5d",
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]