* configure.ac: Added gdb.modula2/Makefile to AC_OUTPUT.
[deliverable/binutils-gdb.git] / bfd / archive.c
index d2e4e032355fa87573f3daf74f8345c43b9f1efc..e080d3a301da737cc320005239e8d584a5a7003e 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
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
 
@@ -8,7 +8,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -18,7 +18,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /*
 @setfilename archive-info
@@ -74,6 +74,8 @@ DESCRIPTION
 
        Archives are supported in BFD in <<archive.c>>.
 
+SUBSECTION
+       Archive functions
 */
 
 /* Assumes:
@@ -127,8 +129,9 @@ DESCRIPTION
  " 18             " - Long name 18 characters long, extended pseudo-BSD.
  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
+#include "libiberty.h"
 #include "libbfd.h"
 #include "aout/ar.h"
 #include "aout/ranlib.h"
@@ -181,11 +184,13 @@ _bfd_generic_mkarchive (bfd *abfd)
   if (bfd_ardata (abfd) == NULL)
     return FALSE;
 
-  bfd_ardata (abfd)->cache = NULL;
-  bfd_ardata (abfd)->archive_head = NULL;
-  bfd_ardata (abfd)->symdefs = NULL;
-  bfd_ardata (abfd)->extended_names = NULL;
-  bfd_ardata (abfd)->tdata = NULL;
+  /* Already cleared by bfd_zalloc above.
+     bfd_ardata (abfd)->cache = NULL;
+     bfd_ardata (abfd)->archive_head = NULL;
+     bfd_ardata (abfd)->symdefs = NULL;
+     bfd_ardata (abfd)->extended_names = NULL;
+     bfd_ardata (abfd)->extended_names_size = 0;
+     bfd_ardata (abfd)->tdata = NULL;  */
 
   return TRUE;
 }
@@ -334,7 +339,7 @@ get_extended_arelt_filename (bfd *arch, const char *name)
   errno = 0;
   /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */
   index = strtol (name + 1, NULL, 10);
-  if (errno != 0)
+  if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
     {
       bfd_set_error (bfd_error_malformed_archive);
       return NULL;
@@ -404,10 +409,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
     {
       filename = get_extended_arelt_filename (abfd, hdr.ar_name);
       if (filename == NULL)
-       {
-         bfd_set_error (bfd_error_malformed_archive);
-         return NULL;
-       }
+       return NULL;
     }
   /* BSD4.4-style long filename.
      Only implemented for reading, so far!  */
@@ -628,11 +630,13 @@ bfd_generic_archive_p (bfd *abfd)
     }
 
   bfd_ardata (abfd)->first_file_filepos = SARMAG;
-  bfd_ardata (abfd)->cache = NULL;
-  bfd_ardata (abfd)->archive_head = NULL;
-  bfd_ardata (abfd)->symdefs = NULL;
-  bfd_ardata (abfd)->extended_names = NULL;
-  bfd_ardata (abfd)->tdata = NULL;
+  /* Cleared by bfd_zalloc above.
+     bfd_ardata (abfd)->cache = NULL;
+     bfd_ardata (abfd)->archive_head = NULL;
+     bfd_ardata (abfd)->symdefs = NULL;
+     bfd_ardata (abfd)->extended_names = NULL;
+     bfd_ardata (abfd)->extended_names_size = 0;
+     bfd_ardata (abfd)->tdata = NULL;  */
 
   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
       || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
@@ -662,10 +666,7 @@ bfd_generic_archive_p (bfd *abfd)
       first = bfd_openr_next_archived_file (abfd, NULL);
       if (first != NULL)
        {
-         bfd_boolean fail;
-
          first->target_defaulted = FALSE;
-         fail = FALSE;
          if (bfd_check_format (first, bfd_object)
              && first->xvec != abfd->xvec)
            {
@@ -697,7 +698,8 @@ bfd_generic_archive_p (bfd *abfd)
 /* The size of the string count.  */
 #define BSD_STRING_COUNT_SIZE 4
 
-/* Returns FALSE on error, TRUE otherwise.  */
+/* Read a BSD-style archive symbol table.  Returns FALSE on error,
+   TRUE otherwise.  */
 
 static bfd_boolean
 do_slurp_bsd_armap (bfd *abfd)
@@ -767,7 +769,8 @@ do_slurp_bsd_armap (bfd *abfd)
   return TRUE;
 }
 
-/* Returns FALSE on error, TRUE otherwise.  */
+/* Read a COFF archive symbol table.  Returns FALSE on error, TRUE
+   otherwise.  */
 
 static bfd_boolean
 do_slurp_coff_armap (bfd *abfd)
@@ -821,9 +824,15 @@ do_slurp_coff_armap (bfd *abfd)
   /* The coff armap must be read sequentially.  So we construct a
      bsd-style one in core all at once, for simplicity.  */
 
+  if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
+    return FALSE;
+
   carsym_size = (nsymz * sizeof (carsym));
   ptrsize = (4 * nsymz);
 
+  if (carsym_size + stringsize + 1 <= carsym_size)
+    return FALSE;
+
   ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1);
   if (ardata->symdefs == NULL)
     return FALSE;
@@ -888,8 +897,8 @@ release_symdefs:
   return FALSE;
 }
 
-/* This routine can handle either coff-style or bsd-style armaps.
-   Returns FALSE on error, TRUE otherwise */
+/* This routine can handle either coff-style or bsd-style armaps
+   (archive symbol table).  Returns FALSE on error, TRUE otherwise */
 
 bfd_boolean
 bfd_slurp_armap (bfd *abfd)
@@ -905,12 +914,12 @@ bfd_slurp_armap (bfd *abfd)
   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
     return FALSE;
 
-  if (!strncmp (nextname, "__.SYMDEF       ", 16)
-      || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* old Linux archives */
+  if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
+      || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
     return do_slurp_bsd_armap (abfd);
-  else if (!strncmp (nextname, "/               ", 16))
+  else if (CONST_STRNEQ (nextname, "/               "))
     return do_slurp_coff_armap (abfd);
-  else if (!strncmp (nextname, "/SYM64/         ", 16))
+  else if (CONST_STRNEQ (nextname, "/SYM64/         "))
     {
       /* 64bit ELF (Irix 6) archive.  */
 #ifdef BFD64
@@ -956,11 +965,11 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd)
   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
     return FALSE;
 
-  if (!strncmp (nextname, "__.SYMDEF       ", 16)
-      || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* Old Linux archives.  */
+  if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
+      || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
     return do_slurp_bsd_armap (abfd);
 
-  if (strncmp (nextname, "/               ", 16))
+  if (! CONST_STRNEQ (nextname, "/               "))
     {
       bfd_has_map (abfd) = FALSE;
       return TRUE;
@@ -1056,10 +1065,11 @@ _bfd_slurp_extended_name_table (bfd *abfd)
       if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
        return FALSE;
 
-      if (strncmp (nextname, "ARFILENAMES/    ", 16) != 0 &&
-         strncmp (nextname, "//              ", 16) != 0)
+      if (! CONST_STRNEQ (nextname, "ARFILENAMES/    ")
+         && ! CONST_STRNEQ (nextname, "//              "))
        {
          bfd_ardata (abfd)->extended_names = NULL;
+         bfd_ardata (abfd)->extended_names_size = 0;
          return TRUE;
        }
 
@@ -1068,7 +1078,11 @@ _bfd_slurp_extended_name_table (bfd *abfd)
        return FALSE;
 
       amt = namedata->parsed_size;
-      bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt);
+      if (amt + 1 == 0)
+        goto byebye;
+
+      bfd_ardata (abfd)->extended_names_size = amt;
+      bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt + 1);
       if (bfd_ardata (abfd)->extended_names == NULL)
        {
        byebye:
@@ -1091,15 +1105,17 @@ _bfd_slurp_extended_name_table (bfd *abfd)
         trailing '/'.  DOS/NT created archive often have \ in them
         We'll fix all problems here..  */
       {
-       char *temp = bfd_ardata (abfd)->extended_names;
+        char *ext_names = bfd_ardata (abfd)->extended_names;
+       char *temp = ext_names;
        char *limit = temp + namedata->parsed_size;
        for (; temp < limit; ++temp)
          {
            if (*temp == '\012')
-             temp[temp[-1] == '/' ? -1 : 0] = '\0';
+             temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
            if (*temp == '\\')
              *temp = '/';
          }
+       *limit = '\0';
       }
 
       /* Pad to an even boundary if you have to.  */
@@ -1220,7 +1236,9 @@ _bfd_construct_extended_name_table (bfd *abfd,
   *tablen = 0;
 
   /* Figure out how long the table should be.  */
-  for (current = abfd->archive_head; current != NULL; current = current->next)
+  for (current = abfd->archive_head;
+       current != NULL;
+       current = current->archive_next)
     {
       const char *normal;
       unsigned int thislen;
@@ -1272,8 +1290,9 @@ _bfd_construct_extended_name_table (bfd *abfd,
   *tablen = total_namelen;
   strptr = *tabloc;
 
-  for (current = abfd->archive_head; current != NULL; current =
-       current->next)
+  for (current = abfd->archive_head;
+       current != NULL;
+       current = current->archive_next)
     {
       const char *normal;
       unsigned int thislen;
@@ -1322,7 +1341,7 @@ hpux_uid_gid_encode (char str[6], long int id)
   str[5] = '@' + (id & 3);
   id >>= 2;
 
-  for (cnt = 4; cnt >= 0; ++cnt, id >>= 6)
+  for (cnt = 4; cnt >= 0; --cnt, id >>= 6)
     str[cnt] = ' ' + (id & 0x3f);
 }
 #endif /* HPUX_LARGE_AR_IDS */
@@ -1623,7 +1642,9 @@ _bfd_write_archive_contents (bfd *arch)
   /* Verify the viability of all entries; if any of them live in the
      filesystem (as opposed to living in an archive open for input)
      then construct a fresh ar_hdr for them.  */
-  for (current = arch->archive_head; current; current = current->next)
+  for (current = arch->archive_head;
+       current != NULL;
+       current = current->archive_next)
     {
       /* This check is checking the bfds for the objects we're reading
         from (which are usually either an object file or archive on
@@ -1633,14 +1654,14 @@ _bfd_write_archive_contents (bfd *arch)
       if (bfd_write_p (current))
        {
          bfd_set_error (bfd_error_invalid_operation);
-         return FALSE;
+         goto input_err;
        }
       if (!current->arelt_data)
        {
          current->arelt_data =
            bfd_ar_hdr_from_filesystem (arch, current->filename, current);
          if (!current->arelt_data)
-           return FALSE;
+           goto input_err;
 
          /* Put in the file name.  */
          BFD_SEND (arch, _bfd_truncate_arname,
@@ -1691,7 +1712,9 @@ _bfd_write_archive_contents (bfd *arch)
        }
     }
 
-  for (current = arch->archive_head; current; current = current->next)
+  for (current = arch->archive_head;
+       current != NULL;
+       current = current->archive_next)
     {
       char buffer[DEFAULT_BUFFERSIZE];
       unsigned int remaining = arelt_size (current);
@@ -1702,7 +1725,7 @@ _bfd_write_archive_contents (bfd *arch)
          != sizeof (*hdr))
        return FALSE;
       if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
-       return FALSE;
+       goto input_err;
       while (remaining)
        {
          unsigned int amt = DEFAULT_BUFFERSIZE;
@@ -1712,8 +1735,8 @@ _bfd_write_archive_contents (bfd *arch)
          if (bfd_bread (buffer, amt, current) != amt)
            {
              if (bfd_get_error () != bfd_error_system_call)
-               bfd_set_error (bfd_error_malformed_archive);
-             return FALSE;
+               bfd_set_error (bfd_error_file_truncated);
+             goto input_err;
            }
          if (bfd_bwrite (buffer, amt, arch) != amt)
            return FALSE;
@@ -1746,6 +1769,10 @@ _bfd_write_archive_contents (bfd *arch)
     }
 
   return TRUE;
+
+ input_err:
+  bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
+  return FALSE;
 }
 \f
 /* Note that the namidx for the first symbol is 0.  */
@@ -1784,12 +1811,12 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
   /* Drop all the files called __.SYMDEF, we're going to make our own.  */
   while (arch->archive_head &&
         strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
-    arch->archive_head = arch->archive_head->next;
+    arch->archive_head = arch->archive_head->archive_next;
 
   /* Map over each element.  */
   for (current = arch->archive_head;
        current != NULL;
-       current = current->next, elt_no++)
+       current = current->archive_next, elt_no++)
     {
       if (bfd_check_format (current, bfd_object)
          && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
@@ -1946,7 +1973,7 @@ bsd_write_armap (bfd *arch,
            {
              firstreal += arelt_size (current) + sizeof (struct ar_hdr);
              firstreal += firstreal % 2;
-             current = current->next;
+             current = current->archive_next;
            }
          while (current != map[count].u.abfd);
        }
@@ -2116,7 +2143,7 @@ coff_write_armap (bfd *arch,
       archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
       /* Remember aboout the even alignment.  */
       archive_member_file_ptr += archive_member_file_ptr % 2;
-      current = current->next;
+      current = current->archive_next;
     }
 
   /* Now write the strings themselves.  */
This page took 0.030957 seconds and 4 git commands to generate.