summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2014-12-29 00:53:27 +0100
committerMark Wielaard <mjw@redhat.com>2015-01-15 14:00:42 +0100
commit0a545e678f2c0605ba050b4f72080572ac7c8470 (patch)
tree8e432b81071a7d1b269794c08e123a917d274b85
parent47efc3bef9f39a0494f9957b2e5f7da33482865b (diff)
downloadelfutils-0a545e678f2c0605ba050b4f72080572ac7c8470.tar.gz
elflint: Add various low-level checks.
elflint could crash or hang because it didn't check some low level issues. https://bugzilla.redhat.com/show_bug.cgi?id=1170810 Reported-by: Alexander Cherepanov <cherepan@mccme.ru> Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r--src/ChangeLog25
-rw-r--r--src/elflint.c263
2 files changed, 236 insertions, 52 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 66d62705..5adf07d9 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,28 @@
+2014-12-30 Mark Wielaard <mjw@redhat.com>
+
+ * elflint.c (check_scn_group): Check d_buf and name are not NULL.
+ (is_rel_dyn): Check d is not NULL. Check shdr->sh_entsize is not
+ zero.
+ (check_dynamic): Check strshdr is not NULL. Check d_tag is positive.
+ (check_symtab_shndx): Check symshdr and data->d_buf are not NULL.
+ Check shdr and symshdr sh_entsize are not zero.
+ (check_gnu_hash): Make sure maskidx is smaller than bitmask_words.
+ Check symshdr->sh_entsize is not zero. Check data->d_buf is not
+ NULL.
+ (compare_hash_gnu_hash): Check sections d_buf are not NULL.
+ Check section data is large enough. Use gnu_symbias.
+ (check_group): Check section val is valid.
+ (has_copy_reloc): Check sh_entsize is not zero.
+ (check_versym): Likewise.
+ (unknown_dependency_p): Likewise.
+ (check_verneed): Break on invalid ref or offset. Don't assert.
+ Report error when next offset is zero, but more vers expected.
+ (check_verdef): Likewise.
+ (check_attributes): Make sure d_buf is not NULL.
+ (check_note): Likewise.
+ (check_note_section): Likewise.
+ (check_program_header): Make sure section name is not NULL.
+
2014-12-26 Mark Wielaard <mjw@redhat.com>
* strings.c (read_elf): Produce error when section data falls outside
diff --git a/src/elflint.c b/src/elflint.c
index 7e732531..143424c6 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -554,7 +554,8 @@ check_scn_group (Ebl *ebl, int idx)
continue;
Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL || data->d_size < sizeof (Elf32_Word))
+ if (data == NULL || data->d_buf == NULL
+ || data->d_size < sizeof (Elf32_Word))
/* Cannot check the section. */
continue;
@@ -692,8 +693,8 @@ section [%2d] '%s': symbol %zu: invalid name value\n"),
else
{
name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
- assert (name != NULL
- || strshdr->sh_type != SHT_STRTAB);
+ if (name == NULL)
+ name = "";
}
if (sym->st_shndx == SHN_XINDEX)
@@ -1061,12 +1062,17 @@ is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
if (rcshdr == NULL)
break;
- if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize)
+ if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize != 0)
{
/* Found the dynamic section. Look through it. */
Elf_Data *d = elf_getdata (scn, NULL);
size_t cnt;
+ if (d == NULL)
+ ERROR (gettext ("\
+section [%2d] '%s': cannot get section data.\n"),
+ idx, section_name (ebl, idx));
+
for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
{
GElf_Dyn dyn_mem;
@@ -1099,7 +1105,7 @@ section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
relative. */
Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
idx), NULL);
- if (reldata != NULL)
+ if (reldata != NULL && shdr->sh_entsize != 0)
for (size_t inner = 0;
inner < shdr->sh_size / shdr->sh_entsize;
++inner)
@@ -1141,7 +1147,8 @@ section [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
/* Does the number specified number of relative
relocations exceed the total number of
relocations? */
- if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
+ if (shdr->sh_entsize != 0
+ && dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
ERROR (gettext ("\
section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
idx, section_name (ebl, idx),
@@ -1151,7 +1158,7 @@ section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
relative. */
Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
idx), NULL);
- if (reldata != NULL)
+ if (reldata != NULL && shdr->sh_entsize != 0)
for (size_t inner = 0;
inner < shdr->sh_size / shdr->sh_entsize;
++inner)
@@ -1284,7 +1291,7 @@ section [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
Elf_Data *dyndata = elf_getdata (dynscn, NULL);
if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
- && dyndata != NULL)
+ && dyndata != NULL && dynshdr->sh_entsize != 0)
for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
{
GElf_Dyn dyn_mem;
@@ -1622,6 +1629,13 @@ check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
shdr->sh_link, section_name (ebl, shdr->sh_link),
idx, section_name (ebl, idx));
+ else if (strshdr == NULL)
+ {
+ ERROR (gettext ("\
+section [%2d]: referenced as string table for section [%2d] '%s' but section link value is invalid\n"),
+ shdr->sh_link, idx, section_name (ebl, idx));
+ return;
+ }
size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
if (shdr->sh_entsize != sh_entsize)
@@ -1685,10 +1699,10 @@ section [%2d] '%s': entry %zu: level 2 tag %s used\n"),
has_dt[dyn->d_tag] = true;
}
- else if (dyn->d_tag <= DT_VALRNGHI
+ else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_VALRNGHI
&& DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
- else if (dyn->d_tag <= DT_ADDRRNGHI
+ else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_ADDRRNGHI
&& DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
@@ -1896,6 +1910,10 @@ section [%2d] '%s': only relocatable files can have extended section index\n"),
ERROR (gettext ("\
section [%2d] '%s': extended section index section not for symbol table\n"),
idx, section_name (ebl, idx));
+ else if (symshdr == NULL)
+ ERROR (gettext ("\
+section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"),
+ idx, section_name (ebl, idx), shdr->sh_link);
Elf_Data *symdata = elf_getdata (symscn, NULL);
if (symdata == NULL)
ERROR (gettext ("cannot get data for symbol section\n"));
@@ -1906,8 +1924,8 @@ section [%2d] '%s': entry size does not match Elf32_Word\n"),
idx, section_name (ebl, idx));
if (symshdr != NULL
- && shdr->sh_entsize
- && symshdr->sh_entsize
+ && shdr->sh_entsize != 0
+ && symshdr->sh_entsize != 0
&& (shdr->sh_size / shdr->sh_entsize
< symshdr->sh_size / symshdr->sh_entsize))
ERROR (gettext ("\
@@ -1934,7 +1952,7 @@ section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same
}
Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL)
+ if (data == NULL || data->d_buf == NULL)
{
ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
idx, section_name (ebl, idx));
@@ -2033,7 +2051,7 @@ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
size_t maxidx = nchain;
- if (symshdr != NULL)
+ if (symshdr != NULL && symshdr->sh_entsize != 0)
{
size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
@@ -2104,7 +2122,7 @@ section [%2d] '%s': 2nd hash function shift too big: %u\n"),
size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
+ nbuckets);
- if (symshdr != NULL)
+ if (symshdr != NULL && symshdr->sh_entsize != 0)
maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
/* We need the symbol section data. */
@@ -2155,8 +2173,10 @@ section [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"
idx, section_name (ebl, idx), symidx,
cnt - (4 + bitmask_words));
- const char *symname = elf_strptr (ebl->elf, symshdr->sh_link,
- sym->st_name);
+ const char *symname = (sym != NULL
+ ? elf_strptr (ebl->elf, symshdr->sh_link,
+ sym->st_name)
+ : NULL);
if (symname != NULL)
{
Elf32_Word hval = elf_gnu_hash (symname);
@@ -2168,6 +2188,14 @@ section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
/* Set the bits in the bitmask. */
size_t maskidx = (hval / classbits) & bitmask_idxmask;
+ if (maskidx >= bitmask_words)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"),
+ idx, section_name (ebl, idx), symidx,
+ cnt - (4 + bitmask_words));
+ return;
+ }
if (classbits == 32)
{
collected.p32[maskidx]
@@ -2195,7 +2223,7 @@ section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
ERROR (gettext ("\
section [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
- else if (symshdr != NULL
+ else if (symshdr != NULL && symshdr->sh_entsize != 0
&& symidx > symshdr->sh_size / symshdr->sh_entsize)
ERROR (gettext ("\
section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
@@ -2223,7 +2251,7 @@ section [%2d] '%s': relocatable files cannot have hash tables\n"),
}
Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL)
+ if (data == NULL || data->d_buf == NULL)
{
ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
idx, section_name (ebl, idx));
@@ -2237,6 +2265,10 @@ section [%2d] '%s': relocatable files cannot have hash tables\n"),
ERROR (gettext ("\
section [%2d] '%s': hash table not for dynamic symbol table\n"),
idx, section_name (ebl, idx));
+ else if (symshdr == NULL)
+ ERROR (gettext ("\
+section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
+ idx, section_name (ebl, idx), shdr->sh_link);
if (shdr->sh_entsize != (tag == SHT_GNU_HASH
? (gelf_getclass (ebl->elf) == ELFCLASS32
@@ -2292,7 +2324,8 @@ compare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
if (hash_shdr == NULL || gnu_hash_shdr == NULL
- || hash_data == NULL || gnu_hash_data == NULL)
+ || hash_data == NULL || hash_data->d_buf == NULL
+ || gnu_hash_data == NULL || gnu_hash_data->d_buf == NULL)
/* None of these pointers should be NULL since we used the
sections already. We are careful nonetheless. */
return;
@@ -2313,27 +2346,70 @@ sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
GElf_Shdr sym_shdr_mem;
GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
- if (sym_data == NULL || sym_shdr == NULL)
+ if (sym_data == NULL || sym_data->d_buf == NULL
+ || sym_shdr == NULL || sym_shdr->sh_entsize == 0)
return;
- int nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
+ const char *hash_name;
+ const char *gnu_hash_name;
+ hash_name = elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name);
+ gnu_hash_name = elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name);
+
+ if (gnu_hash_data->d_size < 4 * sizeof (Elf32_Word))
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+ gnu_hash_idx, gnu_hash_name);
+ return;
+ }
+
+ uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
char *used = alloca (nentries);
memset (used, '\0', nentries);
/* First go over the GNU_HASH table and mark the entries as used. */
const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
Elf32_Word gnu_nbucket = gnu_hasharr[0];
+ Elf32_Word gnu_symbias = gnu_hasharr[1];
const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
const Elf32_Word *gnu_bucket = (gnu_hasharr
+ (4 + gnu_hasharr[2] * bitmap_factor));
- const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0] - gnu_hasharr[1];
+ const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0];
+
+ if (gnu_hasharr[2] == 0)
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' has zero bit mask words\n"),
+ gnu_hash_idx, gnu_hash_name);
+ return;
+ }
+
+ uint64_t used_buf = ((4ULL + gnu_hasharr[2] * bitmap_factor + gnu_nbucket)
+ * sizeof (Elf32_Word));
+ uint32_t max_nsyms = (gnu_hash_data->d_size - used_buf) / sizeof (Elf32_Word);
+ if (used_buf > gnu_hash_data->d_size)
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' uses too much data\n"),
+ gnu_hash_idx, gnu_hash_name);
+ return;
+ }
for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
{
- Elf32_Word symidx = gnu_bucket[cnt];
+ Elf32_Word symidx = gnu_bucket[cnt] - gnu_symbias;;
if (symidx != STN_UNDEF)
do
- used[symidx] |= 1;
+ {
+ if (symidx >= max_nsyms || symidx >= nentries)
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' invalid symbol index\n"),
+ gnu_hash_idx, gnu_hash_name);
+ return;
+ }
+ used[symidx] |= 1;
+ }
while ((gnu_chain[symidx++] & 1u) == 0);
}
@@ -2342,37 +2418,82 @@ sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
{
const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
+ if (hash_data->d_size < 2 * sizeof (Elf32_Word))
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+ hash_idx, hash_name);
+ return;
+ }
+
Elf32_Word nbucket = hasharr[0];
+ Elf32_Word nchain = hasharr[1];
+ uint64_t hash_used = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
+ if (hash_used > hash_data->d_size)
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' uses too much data\n"),
+ hash_idx, hash_name);
+ return;
+ }
+
const Elf32_Word *bucket = &hasharr[2];
const Elf32_Word *chain = &hasharr[2 + nbucket];
for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
{
Elf32_Word symidx = bucket[cnt];
- while (symidx != STN_UNDEF)
+ while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
{
used[symidx] |= 2;
symidx = chain[symidx];
}
}
}
- else
+ else if (hash_shdr->sh_entsize == sizeof (Elf64_Word))
{
const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
+ if (hash_data->d_size < 2 * sizeof (Elf32_Word))
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+ hash_idx, hash_name);
+ return;
+ }
+
Elf64_Xword nbucket = hasharr[0];
+ Elf64_Xword nchain = hasharr[1];
+ uint64_t maxwords = hash_data->d_size / sizeof (Elf64_Xword);
+ if (maxwords < 2
+ || maxwords - 2 < nbucket
+ || maxwords - 2 - nbucket < nchain)
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' uses too much data\n"),
+ hash_idx, hash_name);
+ return;
+ }
+
const Elf64_Xword *bucket = &hasharr[2];
const Elf64_Xword *chain = &hasharr[2 + nbucket];
for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
{
Elf64_Xword symidx = bucket[cnt];
- while (symidx != STN_UNDEF)
+ while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
{
used[symidx] |= 2;
symidx = chain[symidx];
}
}
}
+ else
+ {
+ ERROR (gettext ("\
+hash section [%2zu] '%s' invalid sh_entsize\n"),
+ gnu_hash_idx, gnu_hash_name);
+ return;
+ }
/* Now see which entries are not set in one or both hash tables
(unless the symbol is undefined in which case it can be omitted
@@ -2385,7 +2506,7 @@ sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
ERROR (gettext ("section [%2zu] '%s': reference to symbol index 0\n"),
hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
- for (int cnt = 1; cnt < nentries; ++cnt)
+ for (uint32_t cnt = 1; cnt < nentries; ++cnt)
if (used[cnt] != 0 && used[cnt] != 3)
{
if (used[cnt] == 1)
@@ -2474,6 +2595,10 @@ section [%2d] '%s': invalid symbol index in sh_info\n"),
ERROR (gettext ("\
section [%2d] '%s': cannot get symbol for signature\n"),
idx, section_name (ebl, idx));
+ else if (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name) == NULL)
+ ERROR (gettext ("\
+section [%2d] '%s': cannot get symbol name for signature\n"),
+ idx, section_name (ebl, idx));
else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
"") == 0)
ERROR (gettext ("\
@@ -2487,7 +2612,7 @@ section [%2d] '%s': signature symbol cannot be empty string\n"),
}
Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL)
+ if (data == NULL || data->d_buf == NULL)
ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
idx, section_name (ebl, idx), elf_errmsg (-1));
else
@@ -2563,7 +2688,7 @@ section [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP
val, section_name (ebl, val));
}
- if (++scnref[val] == 2)
+ if (val < shnum && ++scnref[val] == 2)
ERROR (gettext ("\
section [%2d] '%s' is contained in more than one section group\n"),
val, section_name (ebl, val));
@@ -2648,7 +2773,7 @@ has_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
return 0;
Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
+ if (data == NULL || shdr->sh_entsize == 0)
return 0;
if (shdr->sh_type == SHT_REL)
@@ -2762,7 +2887,7 @@ section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic s
/* The number of elements in the version symbol table must be the
same as the number of symbols. */
- if (shdr->sh_entsize && symshdr->sh_entsize
+ if (shdr->sh_entsize != 0 && symshdr->sh_entsize != 0
&& (shdr->sh_size / shdr->sh_entsize
!= symshdr->sh_size / symshdr->sh_entsize))
ERROR (gettext ("\
@@ -2771,7 +2896,7 @@ section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\
shdr->sh_link, section_name (ebl, shdr->sh_link));
Elf_Data *symdata = elf_getdata (symscn, NULL);
- if (symdata == NULL)
+ if (symdata == NULL || shdr->sh_entsize == 0)
/* The error has already been reported. */
return;
@@ -2862,7 +2987,8 @@ unknown_dependency_p (Elf *elf, const char *fname)
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
Elf_Data *data = elf_getdata (scn, NULL);
- if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
+ if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC
+ && data != NULL && shdr->sh_entsize != 0)
for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
{
GElf_Dyn dyn_mem;
@@ -2923,9 +3049,12 @@ section [%2d] '%s': entry %d has wrong version %d\n"),
if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
1, EV_CURRENT))
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
- idx, section_name (ebl, idx), cnt);
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
need->vn_file);
@@ -2958,9 +3087,12 @@ section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
aux->vna_name);
if (verstr == NULL)
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
- idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
+ idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
+ break;
+ }
else
{
GElf_Word hashval = elf_hash (verstr);
@@ -2974,7 +3106,6 @@ section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, ex
ver_need);
if (unlikely (res !=0))
{
- assert (res > 0);
ERROR (gettext ("\
section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
idx, section_name (ebl, idx), need->vn_cnt - cnt2,
@@ -3002,9 +3133,20 @@ section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
if ((need->vn_next != 0 || cnt > 0)
&& offset < auxoffset)
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': entry %d has invalid offset to next entry\n"),
- idx, section_name (ebl, idx), cnt);
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
+
+ if (need->vn_next == 0 && cnt > 0)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
}
}
@@ -3081,9 +3223,12 @@ section [%2d] '%s': entry %d has wrong version %d\n"),
if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
1, EV_CURRENT))
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
- idx, section_name (ebl, idx), cnt);
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
unsigned int auxoffset = offset + def->vd_aux;
GElf_Verdaux auxmem;
@@ -3109,7 +3254,6 @@ section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
int res = add_version (NULL, name, def->vd_ndx, ver_def);
if (unlikely (res !=0))
{
- assert (res > 0);
ERROR (gettext ("\
section [%2d] '%s': entry %d has duplicate version name '%s'\n"),
idx, section_name (ebl, idx), cnt, name);
@@ -3129,9 +3273,12 @@ section [%2d] '%s': entry %d has duplicate version name '%s'\n"),
name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
if (name == NULL)
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
- idx, section_name (ebl, idx), cnt);
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
else
{
newname = alloca (sizeof (*newname));
@@ -3160,9 +3307,20 @@ section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
if ((def->vd_next != 0 || cnt > 0)
&& offset < auxoffset)
- ERROR (gettext ("\
+ {
+ ERROR (gettext ("\
section [%2d] '%s': entry %d has invalid offset to next entry\n"),
- idx, section_name (ebl, idx), cnt);
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
+
+ if (def->vd_next == 0 && cnt > 0)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
+ idx, section_name (ebl, idx), cnt);
+ break;
+ }
}
if (!has_base)
@@ -3201,7 +3359,7 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
}
Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL || data->d_size == 0)
+ if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
{
ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
idx, section_name (ebl, idx));
@@ -4084,7 +4242,7 @@ phdr[%d]: no note entries defined for the type of file\n"),
Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
phdr->p_offset, phdr->p_filesz,
ELF_T_NHDR);
- if (data != NULL)
+ if (data != NULL && data->d_buf != NULL)
notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
if (notes_size == 0)
@@ -4103,7 +4261,7 @@ check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL)
+ if (data == NULL || data->d_buf == NULL)
{
ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
idx, section_name (ebl, idx));
@@ -4296,6 +4454,7 @@ program header offset in ELF header and PHDR entry do not match"));
if (shdr != NULL
&& shdr->sh_type == (is_debuginfo
? SHT_NOBITS : SHT_PROGBITS)
+ && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
&& ! strcmp (".eh_frame_hdr",
elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
{