diff options
author | Mark Wielaard <mjw@redhat.com> | 2014-12-04 21:43:44 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2014-12-11 15:10:14 +0100 |
commit | cb73b5a015606a02f952f7eddaba15327f6191fa (patch) | |
tree | 217bc940ebda5bcf26c4be3de047a1fbd5c3359c /libdw/libdwP.h | |
parent | edb079a596b25379828836e501d003f20afdb879 (diff) | |
download | elfutils-cb73b5a015606a02f952f7eddaba15327f6191fa.tar.gz |
libdw: Add overflow checking to __libdw_form_val_len.
Pass endp as argument to __libdw_form_val_len and check we don't read
beyond the end of expected data and don't return lengths that would
overflow.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libdw/libdwP.h')
-rw-r--r-- | libdw/libdwP.h | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 5ccb13c4..351c5b47 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -458,14 +458,16 @@ extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, /* Helper functions for form handling. */ extern size_t __libdw_form_val_compute_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form, - const unsigned char *valp) - __nonnull_attribute__ (1, 2, 4) internal_function; + const unsigned char *valp, + const unsigned char *endp) + __nonnull_attribute__ (1, 2, 4, 5) internal_function; /* Find the length of a form attribute. */ static inline size_t -__nonnull_attribute__ (1, 2, 4) +__nonnull_attribute__ (1, 2, 4, 5) __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, - unsigned int form, const unsigned char *valp) + unsigned int form, const unsigned char *valp, + const unsigned char *endp) { /* Small lookup table of forms with fixed lengths. Absent indexes are initialized 0, so any truly desired 0 is set to 0x80 and masked. */ @@ -483,11 +485,19 @@ __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, { uint8_t len = form_lengths[form]; if (len != 0) - return len & 0x7f; /* Mask to allow 0x80 -> 0. */ + { + len &= 0x7f; /* Mask to allow 0x80 -> 0. */ + if (unlikely (len > (size_t) (endp - valp))) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + return len; + } } /* Other forms require some computation. */ - return __libdw_form_val_compute_len (dbg, cu, form, valp); + return __libdw_form_val_compute_len (dbg, cu, form, valp, endp); } /* Helper function for DW_FORM_ref* handling. */ |