Fix an illegal memory access triggered when trying to examine an input file containin...
[deliverable/binutils-gdb.git] / bfd / bfdwin.c
index 63ad5ed3f53a7023c7c8f2c67516d78f3ed8c13b..6beed1f1ba31815800374859219748da1ccbecea 100644 (file)
@@ -1,6 +1,5 @@
 /* Support for memory-mapped windows into a BFD.
 /* Support for memory-mapped windows into a BFD.
-   Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
    Written by Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -128,17 +127,16 @@ bfd_get_file_window (bfd *abfd,
   if (pagesize == 0)
     abort ();
 
   if (pagesize == 0)
     abort ();
 
-  if (i == 0)
+  if (i == NULL)
     {
       i = bfd_zmalloc (sizeof (bfd_window_internal));
     {
       i = bfd_zmalloc (sizeof (bfd_window_internal));
-      windowp->i = i;
-      if (i == 0)
+      if (i == NULL)
        return FALSE;
        return FALSE;
-      i->data = 0;
+      i->data = NULL;
     }
 #ifdef HAVE_MMAP
   if (ok_to_map
     }
 #ifdef HAVE_MMAP
   if (ok_to_map
-      && (i->data == 0 || i->mapped == 1)
+      && (i->data == NULL || i->mapped == 1)
       && (abfd->flags & BFD_IN_MEMORY) == 0)
     {
       file_ptr file_offset, offset2;
       && (abfd->flags & BFD_IN_MEMORY) == 0)
     {
       file_ptr file_offset, offset2;
@@ -146,7 +144,8 @@ bfd_get_file_window (bfd *abfd,
       int fd;
 
       /* Find the real file and the real offset into it.  */
       int fd;
 
       /* Find the real file and the real offset into it.  */
-      while (abfd->my_archive != NULL)
+      while (abfd->my_archive != NULL
+            && !bfd_is_thin_archive (abfd->my_archive))
        {
          offset += abfd->origin;
          abfd = abfd->my_archive;
        {
          offset += abfd->origin;
          abfd = abfd->my_archive;
@@ -156,9 +155,9 @@ bfd_get_file_window (bfd *abfd,
       if (abfd->iostream == NULL
          && (abfd->iovec == NULL
              || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
       if (abfd->iostream == NULL
          && (abfd->iovec == NULL
              || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
-       return FALSE;
-      fd = fileno ((FILE *) abfd->iostream);
+       goto free_and_fail;
 
 
+      fd = fileno ((FILE *) abfd->iostream);
       /* Compute offsets and size for mmap and for the user's data.  */
       offset2 = offset % pagesize;
       if (offset2 < 0)
       /* Compute offsets and size for mmap and for the user's data.  */
       offset2 = offset % pagesize;
       if (offset2 < 0)
@@ -169,10 +168,10 @@ bfd_get_file_window (bfd *abfd,
       real_size -= real_size % pagesize;
 
       /* If we're re-using a memory region, make sure it's big enough.  */
       real_size -= real_size % pagesize;
 
       /* If we're re-using a memory region, make sure it's big enough.  */
-      if (i->data && i->size < size)
+      if (i->data != NULL && i->size < size)
        {
          munmap (i->data, i->size);
        {
          munmap (i->data, i->size);
-         i->data = 0;
+         i->data = NULL;
        }
       i->data = mmap (i->data, real_size,
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
        }
       i->data = mmap (i->data, real_size,
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
@@ -185,11 +184,10 @@ bfd_get_file_window (bfd *abfd,
          /* An error happened.  Report it, or try using malloc, or
             something.  */
          bfd_set_error (bfd_error_system_call);
          /* An error happened.  Report it, or try using malloc, or
             something.  */
          bfd_set_error (bfd_error_system_call);
-         i->data = 0;
          windowp->data = 0;
          if (debug_windows)
            fprintf (stderr, "\t\tmmap failed!\n");
          windowp->data = 0;
          if (debug_windows)
            fprintf (stderr, "\t\tmmap failed!\n");
-         return FALSE;
+         goto free_and_fail;
        }
       if (debug_windows)
        fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
        }
       if (debug_windows)
        fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
@@ -198,6 +196,8 @@ bfd_get_file_window (bfd *abfd,
       windowp->data = (bfd_byte *) i->data + offset2;
       windowp->size = size;
       i->mapped = 1;
       windowp->data = (bfd_byte *) i->data + offset2;
       windowp->size = size;
       i->mapped = 1;
+      i->refcount = 1;
+      windowp->i = i;
       return TRUE;
     }
   else if (debug_windows)
       return TRUE;
     }
   else if (debug_windows)
@@ -228,15 +228,18 @@ bfd_get_file_window (bfd *abfd,
   if (i->data == NULL)
     {
       if (size_to_alloc == 0)
   if (i->data == NULL)
     {
       if (size_to_alloc == 0)
-       return TRUE;
-      return FALSE;
+       {
+         windowp->i = i;
+         return TRUE;
+       }
+      goto free_and_fail;
     }
   i->refcount = 1;
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
     }
   i->refcount = 1;
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
-    return FALSE;
+    goto free_and_fail;
   i->size = bfd_bread (i->data, size, abfd);
   if (i->size != size)
   i->size = bfd_bread (i->data, size, abfd);
   if (i->size != size)
-    return FALSE;
+    goto free_and_fail;
   i->mapped = 0;
 #ifdef HAVE_MPROTECT
   if (!writable)
   i->mapped = 0;
 #ifdef HAVE_MPROTECT
   if (!writable)
@@ -249,7 +252,13 @@ bfd_get_file_window (bfd *abfd,
 #endif
   windowp->data = i->data;
   windowp->size = i->size;
 #endif
   windowp->data = i->data;
   windowp->size = i->size;
+  windowp->i = i;
   return TRUE;
   return TRUE;
+
+ free_and_fail:
+  /* We have a bfd_window_internal, but an error occurred.  Free it. */
+  free (i);
+  return FALSE;
 }
 
 #endif /* USE_MMAP */
 }
 
 #endif /* USE_MMAP */
This page took 0.025855 seconds and 4 git commands to generate.