/* Zero to warn when linking objects with incompatible wchar_t sizes. */
int no_wchar_size_warning;
+ /* The number of entries in each of the arrays in this strcuture.
+ Used to avoid buffer overruns. */
+ bfd_size_type num_entries;
+
/* tls_type for each local got entry. */
char *local_got_tls_type;
#define elf_arm_tdata(bfd) \
((struct elf_arm_obj_tdata *) (bfd)->tdata.any)
+#define elf32_arm_num_entries(bfd) \
+ (elf_arm_tdata (bfd)->num_entries)
+
#define elf32_arm_local_got_tls_type(bfd) \
(elf_arm_tdata (bfd)->local_got_tls_type)
if (elf_local_got_refcounts (abfd) == NULL)
{
bfd_size_type num_syms;
- bfd_size_type size;
- char *data;
+
+ elf32_arm_num_entries (abfd) = 0;
+
+ /* Whilst it might be tempting to allocate a single block of memory and
+ then divide it up amoungst the arrays in the elf_arm_obj_tdata
+ structure, this interferes with the work of memory checkers looking
+ for buffer overruns. So allocate each array individually. */
num_syms = elf_tdata (abfd)->symtab_hdr.sh_info;
- size = num_syms * (sizeof (bfd_signed_vma)
- + sizeof (bfd_vma)
- + sizeof (struct arm_local_iplt_info *)
- + sizeof (struct fdpic_local)
- + sizeof (char));
- data = bfd_zalloc (abfd, size);
- if (data == NULL)
+
+ elf_local_got_refcounts (abfd) = bfd_zalloc
+ (abfd, num_syms * sizeof (* elf_local_got_refcounts (abfd)));
+
+ if (elf_local_got_refcounts (abfd) == NULL)
return false;
- /* It is important that these all be allocated in descending
- order of required alignment, so that arrays allocated later
- will be sufficiently aligned. */
- elf_local_got_refcounts (abfd) = (bfd_signed_vma *) data;
- data += num_syms * sizeof (bfd_signed_vma);
+ elf32_arm_local_tlsdesc_gotent (abfd) = bfd_zalloc
+ (abfd, num_syms * sizeof (* elf32_arm_local_tlsdesc_gotent (abfd)));
- elf32_arm_local_tlsdesc_gotent (abfd) = (bfd_vma *) data;
- data += num_syms * sizeof (bfd_vma);
+ if (elf32_arm_local_tlsdesc_gotent (abfd) == NULL)
+ return false;
- elf32_arm_local_iplt (abfd) = (struct arm_local_iplt_info **) data;
- data += num_syms * sizeof (struct arm_local_iplt_info *);
+ elf32_arm_local_iplt (abfd) = bfd_zalloc
+ (abfd, num_syms * sizeof (* elf32_arm_local_iplt (abfd)));
- elf32_arm_local_fdpic_cnts (abfd) = (struct fdpic_local *) data;
- data += num_syms * sizeof (struct fdpic_local);
+ if (elf32_arm_local_iplt (abfd) == NULL)
+ return false;
+
+ elf32_arm_local_fdpic_cnts (abfd) = bfd_zalloc
+ (abfd, num_syms * sizeof (* elf32_arm_local_fdpic_cnts (abfd)));
+
+ if (elf32_arm_local_fdpic_cnts (abfd) == NULL)
+ return false;
+
+ elf32_arm_local_got_tls_type (abfd) = bfd_zalloc
+ (abfd, num_syms * sizeof (* elf32_arm_local_got_tls_type (abfd)));
+
+ if (elf32_arm_local_got_tls_type (abfd) == NULL)
+ return false;
+
+ elf32_arm_num_entries (abfd) = num_syms;
- elf32_arm_local_got_tls_type (abfd) = data;
#if GCC_VERSION >= 3000
BFD_ASSERT (__alignof__ (*elf32_arm_local_tlsdesc_gotent (abfd))
<= __alignof__ (*elf_local_got_refcounts (abfd)));
return NULL;
BFD_ASSERT (r_symndx < elf_tdata (abfd)->symtab_hdr.sh_info);
+ BFD_ASSERT (r_symndx < elf32_arm_num_entries (abfd));
ptr = &elf32_arm_local_iplt (abfd)[r_symndx];
if (*ptr == NULL)
*ptr = bfd_zalloc (abfd, sizeof (**ptr));
if (elf32_arm_local_iplt (abfd) == NULL)
return false;
+ if (r_symndx >= elf32_arm_num_entries (abfd))
+ return false;
+
local_iplt = elf32_arm_local_iplt (abfd)[r_symndx];
if (local_iplt == NULL)
return false;
{
BFD_ASSERT (local_got_offsets != NULL);
+ if (r_symndx >= elf32_arm_num_entries (input_bfd))
+ {
+ _bfd_error_handler (_("\
+%pB: expected symbol index in range 0..%lu but found local symbol with index %lu"),
+ input_bfd,
+ (unsigned long) elf32_arm_num_entries (input_bfd),
+ r_symndx);
+ return false;
+ }
off = local_got_offsets[r_symndx];
offplt = local_tlsdesc_gotents[r_symndx];
tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx];
{
struct fdpic_local *local_fdpic_cnts = elf32_arm_local_fdpic_cnts (input_bfd);
int dynindx = elf_section_data (sym_sec->output_section)->dynindx;
+
+ if (r_symndx >= elf32_arm_num_entries (input_bfd))
+ {
+ * error_message = _("local symbol index too big");
+ return bfd_reloc_dangerous;
+ }
+
int offset = local_fdpic_cnts[r_symndx].funcdesc_offset & ~1;
bfd_vma addr = dynreloc_value - sym_sec->output_section->vma;
bfd_vma seg = -1;
struct fdpic_local *local_fdpic_cnts = elf32_arm_local_fdpic_cnts (input_bfd);
Elf_Internal_Rela outrel;
int dynindx = elf_section_data (sym_sec->output_section)->dynindx;
+
+ if (r_symndx >= elf32_arm_num_entries (input_bfd))
+ {
+ * error_message = _("local symbol index too big");
+ return bfd_reloc_dangerous;
+ }
+
int offset = local_fdpic_cnts[r_symndx].funcdesc_offset & ~1;
bfd_vma addr = dynreloc_value - sym_sec->output_section->vma;
bfd_vma seg = -1;
{
if (!elf32_arm_allocate_local_sym_info (abfd))
return false;
+ if (r_symndx >= elf32_arm_num_entries (abfd))
+ return false;
elf32_arm_local_fdpic_cnts (abfd) [r_symndx].gotofffuncdesc_cnt += 1;
elf32_arm_local_fdpic_cnts (abfd) [r_symndx].funcdesc_offset = -1;
}
{
if (!elf32_arm_allocate_local_sym_info (abfd))
return false;
+ if (r_symndx >= elf32_arm_num_entries (abfd))
+ return false;
elf32_arm_local_fdpic_cnts (abfd) [r_symndx].funcdesc_cnt += 1;
elf32_arm_local_fdpic_cnts (abfd) [r_symndx].funcdesc_offset = -1;
}
/* This is a global offset table entry for a local symbol. */
if (!elf32_arm_allocate_local_sym_info (abfd))
return false;
+ if (r_symndx >= elf32_arm_num_entries (abfd))
+ {
+ _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd,
+ r_symndx);
+ return false;
+ }
+
elf_local_got_refcounts (abfd)[r_symndx] += 1;
old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx];
}
++local_got, ++local_iplt_ptr, ++local_tls_type,
++local_tlsdesc_gotent, ++symndx, ++local_fdpic_cnts)
{
+ if (symndx >= elf32_arm_num_entries (ibfd))
+ return false;
+
*local_tlsdesc_gotent = (bfd_vma) -1;
local_iplt = *local_iplt_ptr;
if (local_iplt != NULL)
{
num_syms = elf_symtab_hdr (input_bfd).sh_info;
+ if (num_syms > elf32_arm_num_entries (input_bfd))
+ {
+ _bfd_error_handler (_("\
+%pB: Number of symbols in input file has increased from %lu to %u\n"),
+ input_bfd,
+ (unsigned long) elf32_arm_num_entries (input_bfd),
+ num_syms);
+ return false;
+ }
for (i = 0; i < num_syms; i++)
if (local_iplt[i] != NULL
&& !elf32_arm_output_plt_map_1 (&osi, true,