aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2025-02-05 11:15:11 +0000
committerNick Clifton <nickc@redhat.com>2025-02-05 11:15:11 +0000
commitf9978defb6fab0bd8583942d97c112b0932ac814 (patch)
tree1ea09d56b2bc2b86f95bb8b7df9063d405c0ee03
parent2a81e7ff9e498e2637ca52db3a18752e4d904dd0 (diff)
downloadbinutils-f9978defb6fab0bd8583942d97c112b0932ac814.zip
binutils-f9978defb6fab0bd8583942d97c112b0932ac814.tar.gz
binutils-f9978defb6fab0bd8583942d97c112b0932ac814.tar.bz2
Prevent illegal memory access when indexing into the sym_hashes array of the elf bfd cookie structure.
PR 32636
-rw-r--r--bfd/elflink.c90
1 files changed, 45 insertions, 45 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a31e409..1f12630 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -96,22 +96,37 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
return true;
}
-asection *
-_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
- unsigned long r_symndx,
- bool discard)
+static struct elf_link_hash_entry *
+get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
{
- if (r_symndx >= cookie->locsymcount
- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
+ struct elf_link_hash_entry *h = NULL;
+ if ((r_symndx >= cookie->locsymcount
+ || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ /* Guard against corrupt input. See PR 32636 for an example. */
+ && r_symndx >= cookie->extsymoff)
+ {
h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ }
+
+ return h;
+}
+asection *
+_bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
+ unsigned long r_symndx,
+ bool discard)
+{
+ struct elf_link_hash_entry *h;
+
+ h = get_ext_sym_hash (cookie, r_symndx);
+
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& discarded_section (h->root.u.def.section))
@@ -119,21 +134,20 @@ _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie,
else
return NULL;
}
- else
- {
- /* It's not a relocation against a global symbol,
- but it could be a relocation against a local
- symbol for a discarded section. */
- asection *isec;
- Elf_Internal_Sym *isym;
- /* Need to: get the symbol; get the section. */
- isym = &cookie->locsyms[r_symndx];
- isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx);
- if (isec != NULL
- && discard ? discarded_section (isec) : 1)
- return isec;
- }
+ /* It's not a relocation against a global symbol,
+ but it could be a relocation against a local
+ symbol for a discarded section. */
+ asection *isec;
+ Elf_Internal_Sym *isym;
+
+ /* Need to: get the symbol; get the section. */
+ isym = &cookie->locsyms[r_symndx];
+ isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx);
+ if (isec != NULL
+ && discard ? discarded_section (isec) : 1)
+ return isec;
+
return NULL;
}
@@ -13997,22 +14011,12 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
if (r_symndx == STN_UNDEF)
return NULL;
- if (r_symndx >= cookie->locsymcount
- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+ h = get_ext_sym_hash (cookie, r_symndx);
+
+ if (h != NULL)
{
bool was_marked;
- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
- if (h == NULL)
- {
- info->callbacks->einfo (_("%F%P: corrupt input: %pB\n"),
- sec->owner);
- return NULL;
- }
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
was_marked = h->mark;
h->mark = 1;
/* Keep all aliases of the symbol too. If an object symbol
@@ -15067,17 +15071,12 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
if (r_symndx == STN_UNDEF)
return true;
- if (r_symndx >= rcookie->locsymcount
- || ELF_ST_BIND (rcookie->locsyms[r_symndx].st_info) != STB_LOCAL)
- {
- struct elf_link_hash_entry *h;
-
- h = rcookie->sym_hashes[r_symndx - rcookie->extsymoff];
-
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ struct elf_link_hash_entry *h;
+ h = get_ext_sym_hash (rcookie, r_symndx);
+
+ if (h != NULL)
+ {
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->owner != rcookie->abfd
@@ -15101,6 +15100,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
|| discarded_section (isec)))
return true;
}
+
return false;
}
return false;