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]

ar mishandles files bigger than 2GB


I created a bug concerning this issue (#652887) but my understanding is 
that patches should be sent here for discussion and to get them applied. 
I apologize if I'm mistaken.

In any case, here's the first patch in the 5 patch series fixing this 
issue. Let me know if I should also send the others here. The patches 
are also attached to the bug:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=652887


So one of the first problems in handling files bigger than 2GB is that 
in the BFD library we use a long to write the size as a string to the 
archive element header. On a 32bit platform this results in a negative 
or truncated file size even though support for large files is enabled.

So this first patch encapsulates writing the size header field in the 
_bfd_ar_sizepad() function.

-- 
Francois Gouget <fgouget@codeweavers.com>
commit 75bf1d978bc03a07ad59a3f983c806bb5899c28c
Author: Francois Gouget <fgouget@codeweavers.com>
Date:   Tue Dec 20 18:37:16 2011 +0100

    bfd: Fix writing the size of 2+GB elements in the archive.

diff --git a/bfd/archive.c b/bfd/archive.c
index 3e333c7..5c5b3d4 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -179,6 +179,22 @@ _bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
     memcpy (p, buf, n);
 }
 
+void
+_bfd_ar_sizepad (char *p, size_t n, bfd_size_type size)
+{
+  static char buf[21];
+  size_t len;
+  snprintf (buf, sizeof (buf), "%-10" BFD_VMA_FMT "u", size);
+  len = strlen (buf);
+  if (len < n)
+    {
+      memcpy (p, buf, len);
+      memset (p + len, ' ', n - len);
+    }
+  else
+    memcpy (p, buf, n);
+}
+
 bfd_boolean
 _bfd_generic_mkarchive (bfd *abfd)
 {
@@ -1770,7 +1786,7 @@ _bfd_bsd44_write_ar_hdr (bfd *archive, bfd *abfd)
 
       BFD_ASSERT (padded_len == arch_eltdata (abfd)->extra_size);
 
-      _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
+      _bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size),
                         arch_eltdata (abfd)->parsed_size + padded_len);
 
       if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
@@ -1891,7 +1907,7 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
                       status.st_gid);
   _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo",
                     status.st_mode);
-  _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
+  _bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size),
                     status.st_size);
   memcpy (hdr->ar_fmag, ARFMAG, 2);
   ared->parsed_size = status.st_size;
@@ -2132,7 +2148,7 @@ _bfd_write_archive_contents (bfd *arch)
       memset (&hdr, ' ', sizeof (struct ar_hdr));
       memcpy (hdr.ar_name, ename, strlen (ename));
       /* Round size up to even number in archive header.  */
-      _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
+      _bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size),
                         (elength + 1) & ~(bfd_size_type) 1);
       memcpy (hdr.ar_fmag, ARFMAG, 2);
       if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
@@ -2409,7 +2425,7 @@ bsd_write_armap (bfd *arch,
                     bfd_ardata (arch)->armap_timestamp);
   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", uid);
   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", gid);
-  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
+  _bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize);
   memcpy (hdr.ar_fmag, ARFMAG, 2);
   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
       != sizeof (struct ar_hdr))
@@ -2564,8 +2580,7 @@ coff_write_armap (bfd *arch,
 
   memset (&hdr, ' ', sizeof (struct ar_hdr));
   hdr.ar_name[0] = '/';
-  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
-                    mapsize);
+  _bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize);
   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
                     ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0
                      ? time (NULL) : 0));
diff --git a/bfd/archive64.c b/bfd/archive64.c
index bbc4c3f..a906508 100644
--- a/bfd/archive64.c
+++ b/bfd/archive64.c
@@ -169,7 +169,7 @@ bfd_elf64_archive_write_armap (bfd *arch,
 
   memset (&hdr, ' ', sizeof (struct ar_hdr));
   memcpy (hdr.ar_name, "/SYM64/", strlen ("/SYM64/"));
-  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
+  _bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size),
                     mapsize);
   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
                     time (NULL));
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 7db09e4..57197ac 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -203,6 +203,8 @@ extern void *_bfd_generic_read_ar_hdr
   (bfd *);
 extern void _bfd_ar_spacepad
   (char *, size_t, const char *, long);
+extern void _bfd_ar_sizepad
+  (char *, size_t, bfd_size_type);
 
 extern void *_bfd_generic_read_ar_hdr_mag
   (bfd *, const char *);
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 0beddb6..121e865 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -208,6 +208,8 @@ extern void *_bfd_generic_read_ar_hdr
   (bfd *);
 extern void _bfd_ar_spacepad
   (char *, size_t, const char *, long);
+extern void _bfd_ar_sizepad
+  (char *, size_t, bfd_size_type);
 
 extern void *_bfd_generic_read_ar_hdr_mag
   (bfd *, const char *);

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