This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: PR ld/5788: Linker memory corruption
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: "Jakub Jelinek" <jakub at redhat dot com>
- Date: Fri, 22 Feb 2008 15:51:23 -0800
- Subject: PATCH: PR ld/5788: Linker memory corruption
Hi Jakub,
This patch
http://sourceware.org/ml/binutils/2007-02/msg00006.html
causes a serious memory corruption in linker. There are 2 problems in
elf_create_symbuf:
ssymbuf = bfd_malloc ((shndx_count + 1) * sizeof (*ssymbuf)
+ (indbufend - indbuf) * sizeof (*ssymbuf));
if (ssymbuf == NULL)
{
free (indbuf);
return NULL;
}
ssym = (struct elf_symbuf_symbol *) (ssymbuf + shndx_count);
ssymbuf->ssym = NULL;
ssymbuf->count = shndx_count;
ssymbuf->st_shndx = 0;
1. Only one combined buffer is allocated for both ssymbuf and ssym.
But it is wrong to assume that size of ssym is the same as ssymbuf.
2. There are shndx_count + 1 entries in ssymbuf. ssym should
start at ssymbuf + shndx_count + 1, not ssymbuf + shndx_count
since the first entry is for shndx_count.
I am checking in this patch as an obvious fix.
H.J.
2008-02-22 H.J. Lu <hongjiu.lu@intel.com>
PR ld/5788
* elflink.c (elf_create_symbuf): Correct buffer size and
position.
--- bfd/elflink.c.group 2008-02-22 11:17:10.000000000 -0800
+++ bfd/elflink.c 2008-02-22 15:37:48.000000000 -0800
@@ -6868,7 +6868,7 @@ elf_create_symbuf (bfd_size_type symcoun
Elf_Internal_Sym **ind, **indbufend, **indbuf;
struct elf_symbuf_symbol *ssym;
struct elf_symbuf_head *ssymbuf, *ssymhead;
- bfd_size_type i, shndx_count;
+ bfd_size_type i, shndx_count, total_size;
indbuf = bfd_malloc2 (symcount, sizeof (*indbuf));
if (indbuf == NULL)
@@ -6888,15 +6888,16 @@ elf_create_symbuf (bfd_size_type symcoun
if (ind[0]->st_shndx != ind[1]->st_shndx)
shndx_count++;
- ssymbuf = bfd_malloc ((shndx_count + 1) * sizeof (*ssymbuf)
- + (indbufend - indbuf) * sizeof (*ssymbuf));
+ total_size = ((shndx_count + 1) * sizeof (*ssymbuf)
+ + (indbufend - indbuf) * sizeof (*ssym));
+ ssymbuf = bfd_malloc (total_size);
if (ssymbuf == NULL)
{
free (indbuf);
return NULL;
}
- ssym = (struct elf_symbuf_symbol *) (ssymbuf + shndx_count);
+ ssym = (struct elf_symbuf_symbol *) (ssymbuf + shndx_count + 1);
ssymbuf->ssym = NULL;
ssymbuf->count = shndx_count;
ssymbuf->st_shndx = 0;
@@ -6914,7 +6915,9 @@ elf_create_symbuf (bfd_size_type symcoun
ssym->st_other = (*ind)->st_other;
ssymhead->count++;
}
- BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count);
+ BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count
+ && (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf)
+ == total_size));
free (indbuf);
return ssymbuf;