Prevent a possible seg-fault in the section merging code, by always creating a paddin...
authorNick Clifton <nickc@redhat.com>
Thu, 16 Nov 2017 13:06:22 +0000 (13:06 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 16 Nov 2017 13:06:22 +0000 (13:06 +0000)
* merge.c (sec_merge_emit): Always create padding buffer.  Add
asserts to make sure that the buffer is long enough.

bfd/ChangeLog
bfd/merge.c

index 648006e64f0015a93aeda2fd5f5b34db1ba11851..8e358dd575d1ab990b7b46ec2431b5893544a61a 100644 (file)
@@ -1,3 +1,8 @@
+2017-11-16  Nick Clifton  <nickc@redhat.com>
+
+       * merge.c (sec_merge_emit): Always create padding buffer.  Add
+       asserts to make sure that the buffer is long enough.
+
 2017-11-15  Alan Modra  <amodra@gmail.com>
 
        * bfd.c (union _bfd_doprnt_args): Add "Bad".
index ad8db83ef624f2ebdc4134840bd3b2557f134160..9775f727e3618ff01965f35e602bb9c1767f48f1 100644 (file)
@@ -292,13 +292,15 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry,
   char *pad = NULL;
   bfd_size_type off = 0;
   int alignment_power = sec->output_section->alignment_power;
+  bfd_size_type pad_len;
 
-  if (alignment_power)
-    {
-      pad = (char *) bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
-      if (pad == NULL)
-       return FALSE;
-    }
+  /* FIXME: If alignment_power is 0 then really we should scan the
+     entry list for the largest required alignment and use that.  */
+  pad_len = alignment_power ? ((bfd_size_type) 1 << alignment_power) : 16;
+
+  pad = (char *) bfd_zmalloc (pad_len);
+  if (pad == NULL)
+    return FALSE;
 
   for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
     {
@@ -308,6 +310,7 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry,
       len = -off & (entry->alignment - 1);
       if (len != 0)
        {
+         BFD_ASSERT (len <= pad_len);
          if (contents)
            {
              memcpy (contents + offset, pad, len);
@@ -336,19 +339,18 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry,
   off = sec->size - off;
   if (off != 0)
     {
+      BFD_ASSERT (off <= pad_len);
       if (contents)
        memcpy (contents + offset, pad, off);
       else if (bfd_bwrite (pad, off, abfd) != off)
        goto err;
     }
 
-  if (pad != NULL)
-    free (pad);
+  free (pad);
   return TRUE;
 
  err:
-  if (pad != NULL)
-    free (pad);
+  free (pad);
   return FALSE;
 }