[PATCH] Always call gelf_fsize with EV_CURRENT as argument.
by Mark Wielaard
Don't trust the elf version given by the file. It could be completely
bogus. In which case gelf_fsize just returns zero. Which could cause
divide by zero errors.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c34
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libelf/ChangeLog | 4 ++++
libelf/nlist.c | 2 +-
src/ChangeLog | 5 +++++
src/nm.c | 2 +-
src/strip.c | 19 +++++++------------
5 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index e9c2a8d..312d5cf 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,7 @@
+2015-05-08 Mark Wielaard <mjw(a)redhat.com>
+
+ * nlist.c (nlist): Call gelf_fsize with EV_CURRENT.
+
2015-01-03 Mark Wielaard <mjw(a)redhat.com>
* version_xlate.h (elf_cvt_Verdef): Use memmove to copy src to dest.
diff --git a/libelf/nlist.c b/libelf/nlist.c
index 41e5ff6..89fd081 100644
--- a/libelf/nlist.c
+++ b/libelf/nlist.c
@@ -126,7 +126,7 @@ nlist (const char *filename, struct nlist *nl)
/* How many symbols are there? */
nsyms = (shdr->sh_size
- / INTUSE(gelf_fsize) (elf, ELF_T_SYM, 1, data->d_version));
+ / INTUSE(gelf_fsize) (elf, ELF_T_SYM, 1, EV_CURRENT));
/* Create the hash table. */
table = nlist_fshash_init (nsyms);
diff --git a/src/ChangeLog b/src/ChangeLog
index e79f457..55bd4cc 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-08 Mark Wielaard <mjw(a)redhat.com>
+
+ * nm.c (show_symbols): Call gelf_fsize with EV_CURRENT.
+ * strip.c (handle_elf): Likewise.
+
2015-05-06 Mark Wielaard <mjw(a)redhat.com>
* elflint.c (check_gnu_hash): Return early when 2nd hash function
diff --git a/src/nm.c b/src/nm.c
index 7d20bbb..8d19715 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -1166,7 +1166,7 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
/* Consistency checks. */
if (entsize == 0
- || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, ehdr->e_version))
+ || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
error (0, 0,
gettext ("%s: entry size in section %zd `%s' is not what we expect"),
fullname, elf_ndxscn (scn),
diff --git a/src/strip.c b/src/strip.c
index fd3920d..365b18d 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -810,8 +810,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* Go through all symbols and make sure the section they
reference is not removed. */
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
for (size_t inner = 0;
inner < shdr_info[cnt].data->d_size / elsize;
@@ -1193,8 +1192,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Elf_Data *versiondata = NULL;
Elf_Data *shndxdata = NULL;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
if (shdr_info[cnt].symtab_idx != 0)
{
@@ -1487,8 +1485,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
/* Adjust the nchain value. The symbol table size
changed. We keep the same size for the bucket array. */
@@ -1541,8 +1538,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
/* Adjust the nchain value. The symbol table size
changed. We keep the same size for the bucket array. */
@@ -1611,8 +1607,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
GElf_Half *verstab = (GElf_Half *) verd->d_buf;
/* Walk through the list and */
- size_t elsize = gelf_fsize (elf, verd->d_type, 1,
- ehdr->e_version);
+ size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
if (newsymidx[inner] != 0)
/* Overwriting the same array works since the
@@ -1624,8 +1619,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
verd->d_size = gelf_fsize (newelf, verd->d_type,
symd->d_size
/ gelf_fsize (elf, symd->d_type, 1,
- ehdr->e_version),
- ehdr->e_version);
+ EV_CURRENT),
+ EV_CURRENT);
update_section_size (verd);
break;
--
1.8.3.1
8 years, 11 months
[PATCH] libdwfl: Only intern CU when not EOF marker and cuoff points to a DIE.
by Mark Wielaard
This replaces the two previously proposed patches for libdwfl/cu.c:
libdwfl: Sanity check cu offset before trying to intern.
libdwfl: Arange CU cannot point to the EOF marker.
The issue is kind of the same and still didn't fully solve the root
cause. This patch makes sure we never insert a bogus DIE nor an EOF
marker. It also makes sure that we only tdestroy the lazy_cu_root
when we really don't need it anymore.
The attached patch looks big, but ignoring whitespace/indenting changes
it is simply:
--- a/libdwfl/cu.c
+++ b/libdwfl/cu.c
@@ -171,6 +171,29 @@ compare_cukey (const void *a, const void *b)
static Dwfl_Error
intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
{
+ if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
+ {
+ if (mod->lazycu == 1)
+ {
+ /* This is the EOF marker. Now we have interned all the CUs.
+ One increment in MOD->lazycu counts not having hit EOF yet. */
+ *result = (void *) -1;
+ less_lazy (mod);
+ return DWFL_E_NOERROR;
+ }
+ else
+ {
+ /* Unexpected EOF, most likely a bogus aranges. */
+ return (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+ }
+ }
+
+ /* Make sure the cuoff points to a real DIE. */
+ Dwarf_Die cudie;
+ Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cudie);
+ if (die == NULL)
+ return DWFL_E_LIBDW;
+
struct Dwarf_CU dwkey;
struct dwfl_cu key;
key.die.cu = &dwkey;
@@ -182,16 +205,6 @@ intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
if (*found == &key || *found == NULL)
{
- if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
- {
- /* This is the EOF marker. Now we have interned all the CUs.
- One increment in MOD->lazycu counts not having hit EOF yet. */
- *found = *result = (void *) -1;
- less_lazy (mod);
- return DWFL_E_NOERROR;
- }
- else
- {
/* This is a new entry, meaning we haven't looked at this CU. */
*found = NULL;
@@ -203,15 +216,7 @@ intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
cu->mod = mod;
cu->next = NULL;
cu->lines = NULL;
-
- /* XXX use non-searching lookup */
- Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cu->die);
- if (die == NULL)
- {
- free (cu);
- return DWFL_E_LIBDW;
- }
- assert (die == &cu->die);
+ cu->die = cudie;
struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
* sizeof (mod->cu[0])));
@@ -228,7 +233,6 @@ intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
*found = cu;
}
- }
*result = *found;
return DWFL_E_NOERROR;
<--->
We need to check the cuoff points to a real Dwarf_Die before trying to
intern the cu with tsearch. Otherwise bogus keys might end up in the
search tree with NULL cus. That will cause crashes in compare_cukey
during next insertion or deletion of cus. We also don't want to insert
the EOF marker and unconditionally tdestroy the lazy_cu_root. The EOF
could be caused by bad DWARF from a bogus agranges entry.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c30
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 ++++
libdwfl/cu.c | 84 +++++++++++++++++++++++++++++--------------------------
2 files changed, 49 insertions(+), 40 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index de76378..47f3854 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-07 Mark Wielaard <mjw(a)redhat.com>
+
+ * cu.c (intern_cu): Check for EOF and check cuoff points to a real
+ Dwarf_Die before interning. Explicitly check EOF is expected.
+
2015-05-05 Mark Wielaard <mjw(a)redhat.com>
* dwfl_lineinfo.c (dwfl_lineinfo): Check info->file is valid.
diff --git a/libdwfl/cu.c b/libdwfl/cu.c
index 3ac341e..8f35b6b 100644
--- a/libdwfl/cu.c
+++ b/libdwfl/cu.c
@@ -171,63 +171,67 @@ compare_cukey (const void *a, const void *b)
static Dwfl_Error
intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
{
- struct Dwarf_CU dwkey;
- struct dwfl_cu key;
- key.die.cu = &dwkey;
- dwkey.offset_size = 0;
- dwkey.start = cuoff - (3 * 0 - 4 + 3);
- struct dwfl_cu **found = tsearch (&key, &mod->lazy_cu_root, &compare_cukey);
- if (unlikely (found == NULL))
- return DWFL_E_NOMEM;
-
- if (*found == &key || *found == NULL)
+ if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
{
- if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
+ if (mod->lazycu == 1)
{
/* This is the EOF marker. Now we have interned all the CUs.
One increment in MOD->lazycu counts not having hit EOF yet. */
- *found = *result = (void *) -1;
+ *result = (void *) -1;
less_lazy (mod);
return DWFL_E_NOERROR;
}
else
{
- /* This is a new entry, meaning we haven't looked at this CU. */
+ /* Unexpected EOF, most likely a bogus aranges. */
+ return (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+ }
+ }
- *found = NULL;
+ /* Make sure the cuoff points to a real DIE. */
+ Dwarf_Die cudie;
+ Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cudie);
+ if (die == NULL)
+ return DWFL_E_LIBDW;
- struct dwfl_cu *cu = malloc (sizeof *cu);
- if (unlikely (cu == NULL))
- return DWFL_E_NOMEM;
+ struct Dwarf_CU dwkey;
+ struct dwfl_cu key;
+ key.die.cu = &dwkey;
+ dwkey.offset_size = 0;
+ dwkey.start = cuoff - (3 * 0 - 4 + 3);
+ struct dwfl_cu **found = tsearch (&key, &mod->lazy_cu_root, &compare_cukey);
+ if (unlikely (found == NULL))
+ return DWFL_E_NOMEM;
- cu->mod = mod;
- cu->next = NULL;
- cu->lines = NULL;
+ if (*found == &key || *found == NULL)
+ {
+ /* This is a new entry, meaning we haven't looked at this CU. */
- /* XXX use non-searching lookup */
- Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cu->die);
- if (die == NULL)
- {
- free (cu);
- return DWFL_E_LIBDW;
- }
- assert (die == &cu->die);
+ *found = NULL;
- struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
- * sizeof (mod->cu[0])));
- if (newvec == NULL)
- {
- free (cu);
- return DWFL_E_NOMEM;
- }
- mod->cu = newvec;
+ struct dwfl_cu *cu = malloc (sizeof *cu);
+ if (unlikely (cu == NULL))
+ return DWFL_E_NOMEM;
- mod->cu[mod->ncu++] = cu;
- if (cu->die.cu->start == 0)
- mod->first_cu = cu;
+ cu->mod = mod;
+ cu->next = NULL;
+ cu->lines = NULL;
+ cu->die = cudie;
- *found = cu;
+ struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
+ * sizeof (mod->cu[0])));
+ if (newvec == NULL)
+ {
+ free (cu);
+ return DWFL_E_NOMEM;
}
+ mod->cu = newvec;
+
+ mod->cu[mod->ncu++] = cu;
+ if (cu->die.cu->start == 0)
+ mod->first_cu = cu;
+
+ *found = cu;
}
*result = *found;
--
2.1.0
8 years, 11 months
[PATCH] elflint: Check gnu_hash has enough data and bitmask_words is not zero.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c31
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 3 ++-
src/elflint.c | 26 ++++++++++++++++++++------
2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 089fe93..e79f457 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,7 +1,8 @@
2015-05-06 Mark Wielaard <mjw(a)redhat.com>
* elflint.c (check_gnu_hash): Return early when 2nd hash function
- shift too big.
+ shift too big. Check there is enough data available. Make sure
+ bitmask_words is not zero.
(check_verdef): Use Elf64_Word for shdr->sh_info cnt.
(check_verneed): Likewise.
(check_attributes): Break when vendor name isn't terminated.
diff --git a/src/elflint.c b/src/elflint.c
index df476a1..1c6a55a 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -2091,26 +2091,40 @@ static void
check_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
GElf_Shdr *symshdr)
{
+ if (data->d_size < 4 * sizeof (Elf32_Word))
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': not enough data\n"),
+ idx, section_name (ebl, idx));
+ return;
+ }
+
Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
- if (!powerof2 (bitmask_words))
- ERROR (gettext ("\
-section [%2d] '%s': bitmask size not power of 2: %u\n"),
- idx, section_name (ebl, idx), bitmask_words);
+ if (bitmask_words == 0 || !powerof2 (bitmask_words))
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
+ idx, section_name (ebl, idx), bitmask_words);
+ return;
+ }
size_t bitmask_idxmask = bitmask_words - 1;
if (gelf_getclass (ebl->elf) == ELFCLASS64)
bitmask_words *= 2;
Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
- if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))
+ /* Is there still room for the sym chain?
+ Use uint64_t calculation to prevent 32bit overlow. */
+ uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
+ if (used_buf > data->d_size)
{
ERROR (gettext ("\
section [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
idx, section_name (ebl, idx), (long int) shdr->sh_size,
- (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)));
+ (long int) used_buf);
return;
}
--
2.1.0
8 years, 11 months
[PATCH] elflint: Add sanity checks to check_attributes.
by Mark Wielaard
This is similar to commit 9644aa for readelf print_attributes.
Bail out when the vendor name isn't terminated and add overflow check
for subsection_len.
Note that readelf does handle non-gnu attributes, while elflint doesn't.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 2 ++
src/elflint.c | 6 ++++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 93f4aba..089fe93 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -4,6 +4,8 @@
shift too big.
(check_verdef): Use Elf64_Word for shdr->sh_info cnt.
(check_verneed): Likewise.
+ (check_attributes): Break when vendor name isn't terminated.
+ Add overflow check for subsection_len.
2015-05-05 Mark Wielaard <mjw(a)redhat.com>
diff --git a/src/elflint.c b/src/elflint.c
index 4e53646..df476a1 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3423,7 +3423,7 @@ section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
ERROR (gettext ("\
section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
idx, section_name (ebl, idx), pos (p));
- continue;
+ break;
}
++q;
@@ -3466,7 +3466,9 @@ section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
CONVERT (subsection_len);
- if (p - chunk < (ptrdiff_t) subsection_len)
+ /* Don't overflow, ptrdiff_t might be 32bits, but signed. */
+ if (p - chunk < (ptrdiff_t) subsection_len
+ || subsection_len >= (uint32_t) PTRDIFF_MAX)
{
ERROR (gettext ("\
section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
--
2.1.0
8 years, 11 months
[PATCH] elflint: Use Use Elf64_Word for shdr->sh_info cnt.
by Mark Wielaard
On 32bit using int might overflow.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c31
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 2 ++
src/elflint.c | 8 ++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 486f20f..93f4aba 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -2,6 +2,8 @@
* elflint.c (check_gnu_hash): Return early when 2nd hash function
shift too big.
+ (check_verdef): Use Elf64_Word for shdr->sh_info cnt.
+ (check_verneed): Likewise.
2015-05-05 Mark Wielaard <mjw(a)redhat.com>
diff --git a/src/elflint.c b/src/elflint.c
index 3abda71..4e53646 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3037,8 +3037,10 @@ section [%2d] '%s': sh_link does not link to string table\n"),
return;
}
unsigned int offset = 0;
- for (int cnt = shdr->sh_info; --cnt >= 0; )
+ for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
{
+ cnt--;
+
/* Get the data at the next offset. */
GElf_Verneed needmem;
GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
@@ -3196,8 +3198,10 @@ section [%2d] '%s': sh_link does not link to string table\n"),
bool has_base = false;
unsigned int offset = 0;
- for (int cnt = shdr->sh_info; --cnt >= 0; )
+ for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
{
+ cnt--;
+
/* Get the data at the next offset. */
GElf_Verdef defmem;
GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
--
2.1.0
8 years, 11 months
[PATCH] elflint: Stop checking section when 2nd hash function shift too big.
by Mark Wielaard
Nothing good comes from trying to continue with a bogus hash function.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c31
---
src/ChangeLog | 5 +++++
src/elflint.c | 7 +++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 7a44fc6..486f20f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-06 Mark Wielaard <mjw(a)redhat.com>
+
+ * elflint.c (check_gnu_hash): Return early when 2nd hash function
+ shift too big.
+
2015-05-05 Mark Wielaard <mjw(a)redhat.com>
* nm.c (show_symbols): Handle dwarf_linesrc returning NULL.
diff --git a/src/elflint.c b/src/elflint.c
index a6f9b68..3abda71 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -2115,9 +2115,12 @@ section [%2d] '%s': hash table section is too small (is %ld, expected at least %
}
if (shift > 31)
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': 2nd hash function shift too big: %u\n"),
- idx, section_name (ebl, idx), shift);
+ idx, section_name (ebl, idx), shift);
+ return;
+ }
size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
+ nbuckets);
--
2.1.0
8 years, 11 months
[PATCH] libdw: Detect line number overflow in dwarf_getsrclines on 32bit.
by Mark Wielaard
We do check whether the values we store for the line fit our data
representation in add_new_line, but on 32bit systems we would fail
to notice line overflowing.
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c32
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/dwarf_getsrclines.c | 3 ++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index f5dfc8f..034db11 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-06 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_getsrclines.c (read_srclines): Use an int64_t to store and
+ check the line number.
+
2015-05-05 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getaranges.c (dwarf_getaranges): Check there is enough data
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 368f2fd..5c85fd4 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -302,7 +302,8 @@ read_srclines (Dwarf *dbg,
Dwarf_Word addr = 0;
unsigned int op_index = 0;
unsigned int file = 1;
- int line = 1;
+ /* We only store an int, but want to check for overflow (see SET below). */
+ int64_t line = 1;
unsigned int column = 0;
uint_fast8_t is_stmt = default_is_stmt;
bool basic_block = false;
--
2.1.0
8 years, 11 months
[PATCH] nm: Handle dwarf_linesrc returning NULL.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#32
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/nm.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/nm.c b/src/nm.c
index b6a1e6e..7d20bbb 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -1297,11 +1297,10 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
/* We found the line. */
int lineno;
(void) dwarf_lineno (line, &lineno);
+ const char *file = dwarf_linesrc (line, NULL, NULL);
+ file = (file != NULL) ? basename (file) : "???";
int n;
- n = obstack_printf (&whereob, "%s:%d%c",
- basename (dwarf_linesrc (line,
- NULL,
- NULL)),
+ n = obstack_printf (&whereob, "%s:%d%c", file,
lineno, '\0');
sym_mem[nentries_used].where
= obstack_finish (&whereob);
--
2.1.0
8 years, 11 months
[PATCH] libdw: dwarf_getaranges check there is enough data before reading.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c30
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/dwarf_getaranges.c | 14 +++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index fd3e4ad..f5dfc8f 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2015-05-05 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_getaranges.c (dwarf_getaranges): Check there is enough data
+ left before reading values.
+
2015-05-04 Anthony G. Basile <blueness(a)gentoo.org>
* Makefile.am (libdw_so_SOURCES): Append $(argp_LDADD) to link
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index 4953af5..c03e946 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -110,10 +110,16 @@ dwarf_getaranges (dbg, aranges, naranges)
5. A 1-byte unsigned integer containing the size in bytes of
a segment descriptor on the target system. */
+ if (readp + 4 > readendp)
+ goto invalid;
+
Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
unsigned int length_bytes = 4;
if (length == DWARF3_LENGTH_64_BIT)
{
+ if (readp + 8 > readendp)
+ goto invalid;
+
length = read_8ubyte_unaligned_inc (dbg, readp);
length_bytes = 8;
}
@@ -121,6 +127,9 @@ dwarf_getaranges (dbg, aranges, naranges)
&& length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
goto invalid;
+ if (readp + 2 > readendp)
+ goto invalid;
+
unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
if (version != 2)
{
@@ -136,7 +145,7 @@ dwarf_getaranges (dbg, aranges, naranges)
return -1;
}
- Dwarf_Word offset;
+ Dwarf_Word offset = 0;
if (__libdw_read_offset_inc (dbg,
IDX_debug_aranges, &readp,
length_bytes, &offset, IDX_debug_info, 4))
@@ -164,6 +173,9 @@ dwarf_getaranges (dbg, aranges, naranges)
address_size, &range_address))
goto fail;
+ if (readp + address_size > readendp)
+ goto invalid;
+
if (address_size == 4)
range_length = read_4ubyte_unaligned_inc (dbg, readp);
else
--
2.1.0
8 years, 11 months
[PATCH] libdwfl: Bounds check Dwarf_Fileinfo file number in dwfl_lineinfo.
by Mark Wielaard
https://bugzilla.redhat.com/show_bug.cgi?id=1170810#c30
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 4 ++++
libdwfl/dwfl_lineinfo.c | 8 +++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index b915f44..6945eec 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,7 @@
+2015-05-05 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_lineinfo.c (dwfl_lineinfo): Check info->file is valid.
+
2015-04-21 Mark Wielaard <mjw(a)redhat.com>
* dwfl_error.c (msgstr): Define as const char *.
diff --git a/libdwfl/dwfl_lineinfo.c b/libdwfl/dwfl_lineinfo.c
index dfb27d8..7ddbfb0 100644
--- a/libdwfl/dwfl_lineinfo.c
+++ b/libdwfl/dwfl_lineinfo.c
@@ -1,5 +1,5 @@
/* Get information from a source line record returned by libdwfl.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -46,6 +46,12 @@ dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp,
if (colp != NULL)
*colp = info->column;
+ if (unlikely (info->file >= info->files->nfiles))
+ {
+ __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+ return NULL;
+ }
+
struct Dwarf_Fileinfo_s *file = &info->files->info[info->file];
if (mtime != NULL)
*mtime = file->mtime;
--
2.1.0
8 years, 11 months