This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]