aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index f771754..34100d8 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -289,16 +289,23 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
|| bfd_seek (abfd, offset, SEEK_SET) != 0
- || (shstrtab = _bfd_alloc_and_read (abfd, shstrtabsize + 1,
- shstrtabsize)) == NULL)
+ || (shstrtab
+ = _bfd_mmap_readonly_persistent (abfd, shstrtabsize)) == NULL)
{
/* Once we've failed to read it, make sure we don't keep
trying. Otherwise, we'll keep allocating space for
the string table over and over. */
i_shdrp[shindex]->sh_size = 0;
}
- else
- shstrtab[shstrtabsize] = '\0';
+ else if (shstrtab[shstrtabsize - 1] != '\0')
+ {
+ /* It is an error if a string table isn't terminated. */
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): string table is corrupt"),
+ abfd, i_shdrp[shindex]->bfd_section);
+ return NULL;
+ }
i_shdrp[shindex]->contents = shstrtab;
}
return (char *) shstrtab;
@@ -1897,6 +1904,8 @@ get_hash_table_data (bfd *abfd, bfd_size_type number,
unsigned char *e_data = NULL;
bfd_vma *i_data = NULL;
bfd_size_type size;
+ void *e_data_addr;
+ size_t e_data_size ATTRIBUTE_UNUSED;
if (ent_size != 4 && ent_size != 8)
return NULL;
@@ -1918,7 +1927,8 @@ get_hash_table_data (bfd *abfd, bfd_size_type number,
return NULL;
}
- e_data = _bfd_malloc_and_read (abfd, size, size);
+ e_data = _bfd_mmap_readonly_temporary (abfd, size, &e_data_addr,
+ &e_data_size);
if (e_data == NULL)
return NULL;
@@ -1936,7 +1946,7 @@ get_hash_table_data (bfd *abfd, bfd_size_type number,
while (number--)
i_data[number] = bfd_get_64 (abfd, e_data + number * ent_size);
- free (e_data);
+ _bfd_munmap_readonly_temporary (e_data_addr, e_data_size);
return i_data;
}
@@ -1985,6 +1995,10 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
size_t verneed_size = 0;
size_t extsym_size;
const struct elf_backend_data *bed;
+ void *dynbuf_addr = NULL;
+ void *esymbuf_addr = NULL;
+ size_t dynbuf_size = 0;
+ size_t esymbuf_size = 0;
/* Return TRUE if symbol table is bad. */
if (elf_bad_symtab (abfd))
@@ -2002,7 +2016,9 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
if (bfd_seek (abfd, phdr->p_offset, SEEK_SET) != 0)
goto error_return;
- dynbuf = _bfd_malloc_and_read (abfd, phdr->p_filesz, phdr->p_filesz);
+ dynbuf_size = phdr->p_filesz;
+ dynbuf = _bfd_mmap_readonly_temporary (abfd, dynbuf_size,
+ &dynbuf_addr, &dynbuf_size);
if (dynbuf == NULL)
goto error_return;
@@ -2080,11 +2096,17 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* Dynamic string table must be valid until ABFD is closed. */
- strbuf = (char *) _bfd_alloc_and_read (abfd, dt_strsz + 1, dt_strsz);
+ strbuf = (char *) _bfd_mmap_readonly_persistent (abfd, dt_strsz);
if (strbuf == NULL)
goto error_return;
- /* Since this is a string table, make sure that it is terminated. */
- strbuf[dt_strsz] = 0;
+ if (strbuf[dt_strsz - 1] != 0)
+ {
+ /* It is an error if a string table is't terminated. */
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: DT_STRTAB table is corrupt"), abfd);
+ goto error_return;
+ }
/* Get the real symbol count from DT_HASH or DT_GNU_HASH. Prefer
DT_HASH since it is simpler than DT_GNU_HASH. */
@@ -2259,7 +2281,10 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
if (filepos == (file_ptr) -1
|| bfd_seek (abfd, filepos, SEEK_SET) != 0)
goto error_return;
- esymbuf = _bfd_malloc_and_read (abfd, amt, amt);
+ esymbuf_size = amt;
+ esymbuf = _bfd_mmap_readonly_temporary (abfd, esymbuf_size,
+ &esymbuf_addr,
+ &esymbuf_size);
if (esymbuf == NULL)
goto error_return;
@@ -2303,7 +2328,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERSYM info must be valid until ABFD is closed. */
- versym = _bfd_alloc_and_read (abfd, amt, amt);
+ versym = _bfd_mmap_readonly_persistent (abfd, amt);
if (dt_verdef)
{
@@ -2315,8 +2340,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERDEF info must be valid until ABFD is closed. */
- verdef = _bfd_alloc_and_read (abfd, verdef_size,
- verdef_size);
+ verdef = _bfd_mmap_readonly_persistent (abfd, verdef_size);
}
if (dt_verneed)
@@ -2329,8 +2353,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERNEED info must be valid until ABFD is closed. */
- verneed = _bfd_alloc_and_read (abfd, verneed_size,
- verneed_size);
+ verneed = _bfd_mmap_readonly_persistent (abfd, verneed_size);
}
}
@@ -2353,8 +2376,8 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
/* Restore file position for elf_object_p. */
if (bfd_seek (abfd, saved_filepos, SEEK_SET) != 0)
res = false;
- free (dynbuf);
- free (esymbuf);
+ _bfd_munmap_readonly_temporary (dynbuf_addr, dynbuf_size);
+ _bfd_munmap_readonly_temporary (esymbuf_addr, esymbuf_size);
free (gnubuckets);
free (gnuchains);
free (mipsxlat);
@@ -9413,6 +9436,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
bfd_byte *contents = NULL;
unsigned int freeidx = 0;
size_t amt;
+ void *contents_addr = NULL;
+ size_t contents_size = 0;
if (elf_dynverref (abfd) != 0 || elf_tdata (abfd)->dt_verneed != NULL)
{
@@ -9449,7 +9474,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
goto error_return_verref;
- contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
+ contents_size = hdr->sh_size;
+ contents = _bfd_mmap_readonly_temporary (abfd, contents_size,
+ &contents_addr,
+ &contents_size);
if (contents == NULL)
goto error_return_verref;
@@ -9582,8 +9610,9 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
elf_tdata (abfd)->cverrefs = i;
if (contents != elf_tdata (abfd)->dt_verneed)
- free (contents);
+ _bfd_munmap_readonly_temporary (contents_addr, contents_size);
contents = NULL;
+ contents_addr = NULL;
}
if (elf_dynverdef (abfd) != 0 || elf_tdata (abfd)->dt_verdef != NULL)
@@ -9624,7 +9653,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
goto error_return_verdef;
- contents = _bfd_malloc_and_read (abfd, hdr->sh_size, hdr->sh_size);
+ contents_size = hdr->sh_size;
+ contents = _bfd_mmap_readonly_temporary (abfd, contents_size,
+ &contents_addr,
+ &contents_size);
if (contents == NULL)
goto error_return_verdef;
@@ -9778,8 +9810,9 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
}
if (contents != elf_tdata (abfd)->dt_verdef)
- free (contents);
+ _bfd_munmap_readonly_temporary (contents_addr, contents_size);
contents = NULL;
+ contents_addr = NULL;
}
else if (default_imported_symver)
{
@@ -9835,7 +9868,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
error_return:
if (contents != elf_tdata (abfd)->dt_verneed
&& contents != elf_tdata (abfd)->dt_verdef)
- free (contents);
+ _bfd_munmap_readonly_temporary (contents_addr, contents_size);
return false;
}