PR 12513
authorAlan Modra <amodra@gmail.com>
Mon, 28 Feb 2011 07:46:37 +0000 (07:46 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 28 Feb 2011 07:46:37 +0000 (07:46 +0000)
* archive.c (bfd_slurp_bsd_armap_f2): Sanity check parsed_size and
stringsize.  Properly sanity check symdef_count.  Remove redundant
bfd_release.

bfd/ChangeLog
bfd/archive.c

index 918769190826eac1fdd99695152e89bc84dfbe52..53bf1cf13e2b711d255dcb0a89aefa88053ac446 100644 (file)
@@ -1,3 +1,10 @@
+2011-02-28  Alan Modra  <amodra@gmail.com>
+
+       PR 12513
+       * archive.c (bfd_slurp_bsd_armap_f2): Sanity check parsed_size and
+       stringsize.  Properly sanity check symdef_count.  Remove redundant
+       bfd_release.
+
 2011-02-25  Rafael Ávila de Espíndola <respindola@mozilla.com>
 
        * plugin.c (bfd_plugin_object_p): Correctly set the filesize
index 258c8d9aaedb0bc8958fd4b826ac0848b518ff82..c3aaffc59f5d3b2ffd0cb3446cd671f323788533 100644 (file)
@@ -1,6 +1,6 @@
 /* BFD back-end for archive files (libraries).
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
 
@@ -1109,6 +1109,7 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd)
   struct artdata *ardata = bfd_ardata (abfd);
   char *stringbase;
   unsigned int stringsize;
+  unsigned int left;
   bfd_size_type amt;
   carsym *set;
   int i = bfd_bread (nextname, 16, abfd);
@@ -1136,43 +1137,46 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd)
   if (mapdata == NULL)
     return FALSE;
 
-  amt = mapdata->parsed_size;
-  raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
-  if (raw_armap == NULL)
+  if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
     {
+    wrong_format:
+      bfd_set_error (bfd_error_wrong_format);
     byebye:
       bfd_release (abfd, mapdata);
       return FALSE;
     }
+  left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE;
+
+  amt = mapdata->parsed_size;
+  raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
+  if (raw_armap == NULL)
+    goto byebye;
 
   if (bfd_bread (raw_armap, amt, abfd) != amt)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_malformed_archive);
-    byebyebye:
-      bfd_release (abfd, raw_armap);
       goto byebye;
     }
 
   ardata->symdef_count = H_GET_16 (abfd, raw_armap);
 
-  if (ardata->symdef_count * BSD_SYMDEF_SIZE
-      > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE)
-    {
-      /* Probably we're using the wrong byte ordering.  */
-      bfd_set_error (bfd_error_wrong_format);
-      goto byebyebye;
-    }
-
   ardata->cache = 0;
 
   stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
+  if (stringsize > left)
+    goto wrong_format;
+  left -= stringsize;
+
   /* Skip sym count and string sz.  */
   stringbase = ((char *) raw_armap
                + HPUX_SYMDEF_COUNT_SIZE
                + BSD_STRING_COUNT_SIZE);
   rbase = (bfd_byte *) stringbase + stringsize;
   amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
+  if (amt > left)
+    goto wrong_format;
+
   ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
   if (!ardata->symdefs)
     return FALSE;