Fail when string merge can't alloc memory
authorAlan Modra <amodra@gmail.com>
Fri, 29 Sep 2017 03:37:56 +0000 (13:07 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 29 Sep 2017 05:12:36 +0000 (14:42 +0930)
I was looking at Debian bug #874674 again today, and think I might
have spotted the problem.  It appears that merge.c tries to cope with
memory allocation failures in some circumstances, but doesn't quite
manage to get everything right.  This patch will make ld report memory
allocation failures instead of silently not merging strings.

* merge.c (merge_strings): Return FALSE on malloc failure.
(_bfd_merge_sections): Return failures from record_section and
merge_strings.

bfd/ChangeLog
bfd/merge.c

index 8fca051b8395d229dc3d4d8f795ed2b191d3d6bb..8b44ceb4059c1422ff8ad16d2a58818bc628ddf9 100644 (file)
@@ -1,3 +1,9 @@
+2017-09-29  Alan Modra  <amodra@gmail.com>
+
+       * merge.c (merge_strings): Return FALSE on malloc failure.
+       (_bfd_merge_sections): Return failures from record_section and
+       merge_strings.
+
 2017-09-28  Alan Modra  <amodra@gmail.com>
 
        PR 22220
index a1792a8741bd1d1082ff522ba5d744ff2daded04..ad8db83ef624f2ebdc4134840bd3b2557f134160 100644 (file)
@@ -609,7 +609,7 @@ is_suffix (const struct sec_merge_hash_entry *A,
 
 /* This is a helper function for _bfd_merge_sections.  It attempts to
    merge strings matching suffixes of longer strings.  */
-static void
+static bfd_boolean
 merge_strings (struct sec_merge_info *sinfo)
 {
   struct sec_merge_hash_entry **array, **a, *e;
@@ -621,7 +621,7 @@ merge_strings (struct sec_merge_info *sinfo)
   amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
   array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
   if (array == NULL)
-    goto alloc_failure;
+    return FALSE;
 
   for (e = sinfo->htab->first, a = array; e; e = e->next)
     if (e->alignment)
@@ -666,9 +666,7 @@ merge_strings (struct sec_merge_info *sinfo)
        }
     }
 
-alloc_failure:
-  if (array)
-    free (array);
+  free (array);
 
   /* Now assign positions to the strings we want to keep.  */
   size = 0;
@@ -714,6 +712,7 @@ alloc_failure:
            e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
          }
       }
+  return TRUE;
 }
 
 /* This function is called once after all SEC_MERGE sections are registered
@@ -748,7 +747,7 @@ _bfd_merge_sections (bfd *abfd,
              (*remove_hook) (abfd, secinfo->sec);
          }
        else if (! record_section (sinfo, secinfo))
-         break;
+         return FALSE;
 
       if (secinfo)
        continue;
@@ -757,7 +756,10 @@ _bfd_merge_sections (bfd *abfd,
        continue;
 
       if (sinfo->htab->strings)
-       merge_strings (sinfo);
+       {
+         if (!merge_strings (sinfo))
+           return FALSE;
+       }
       else
        {
          struct sec_merge_hash_entry *e;