This is the mail archive of the binutils-cvs@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]

[binutils-gdb] Fix infinite loop when processing rpath tokens.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e680a6b69b4bd173a180419e973a9bf18a000151

commit e680a6b69b4bd173a180419e973a9bf18a000151
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon Nov 7 15:05:34 2016 +0000

    Fix infinite loop when processing rpath tokens.
    
    	PR ld/20784
    	* emultempl/elf32.em (search_needed): Fix infinite loop when
    	unable to process a token.  Add support for curly braced enclosed
    	tokens.
    	* ld.texinfo (--rpath-link): Document supprot for $ORIGIN and
    	$LIB.

Diff:
---
 ld/ChangeLog          |  9 +++++++
 ld/emultempl/elf32.em | 75 ++++++++++++++++++++++++++++++++-------------------
 ld/ld.texinfo         | 10 +++++++
 3 files changed, 67 insertions(+), 27 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index ae6d732..9d04123 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,14 @@
 2016-11-07  Nick Clifton  <nickc@redhat.com>
 
+	PR ld/20784
+	* emultempl/elf32.em (search_needed): Fix infinite loop when
+	unable to process a token.  Add support for curly braced enclosed
+	tokens.
+	* ld.texinfo (--rpath-link): Document supprot for $ORIGIN and
+	$LIB.
+
+2016-11-07  Nick Clifton  <nickc@redhat.com>
+
 	* ld.texinfo (--compress-debug-sections): Expand documentation of
 	this option.
 
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 57252da..8c63638 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -495,6 +495,7 @@ gld${EMULATION_NAME}_search_needed (const char *path,
   len = strlen (name);
   while (1)
     {
+      unsigned offset = 0;
       char * var;
       char *filename, *sset;
 
@@ -527,8 +528,10 @@ gld${EMULATION_NAME}_search_needed (const char *path,
       /* PR 20535: Support the same pseudo-environment variables that
 	 are supported by ld.so.  Namely, $ORIGIN, $LIB and $PLATFORM.
          Since there can be more than one occurrence of these tokens in
-	 the path we loop until no more are found.  */
-      while ((var = strchr (filename, '$')) != NULL)
+	 the path we loop until no more are found.  Since we might not
+	 be able to substitute some of the tokens we maintain an offset
+	 into the filename for where we should begin our scan.  */
+      while ((var = strchr (filename + offset, '$')) != NULL)
 	{
 	  /* The ld.so manual page does not say, but I am going to assume that
 	     these tokens are terminated by a directory seperator character
@@ -536,13 +539,14 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	     $ORIGIN should only be used at the start of a path, but that is
 	     not enforced here.
 
-	     FIXME: The ld.so manual page also states that it allows ${ORIGIN}
-	     ${LIB} and ${PLATFORM}.  We should support these variants too.
+	     The ld.so manual page also states that it allows ${ORIGIN},
+	     ${LIB} and ${PLATFORM}, so these are supported as well.
 
 	     FIXME: The code could be a lot cleverer about allocating space
 	     for the processed string.  */
 	  char *    end = strchr (var, '/');
 	  char *    replacement = NULL;
+	  char *    v = var + 1;
 	  char *    freeme = NULL;
 	  unsigned  flen = strlen (filename);
 
@@ -550,16 +554,27 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	    /* Temporarily terminate the filename at the end of the token.  */
 	    * end = 0;
 
-	  switch (var[1])
+	  if (*v == '{')
+	    ++ v;
+	  switch (*v++)
 	    {
 	    case 'O':
-	      if (strcmp (var + 2, "RIGIN") == 0)
+	      if (strcmp (v, "RIGIN") == 0 || strcmp (v, "RIGIN}") == 0)
 		{
 		  /* ORIGIN - replace with the full path to the directory
 		     containing the program or shared object.  */
 		  if (needed.by == NULL)
-		    break;
-		  replacement = bfd_get_filename (needed.by);
+		    {
+		      if (link_info.output_bfd == NULL)
+			{
+			  break;
+			}
+		      else
+			replacement = bfd_get_filename (link_info.output_bfd);
+		    }
+		  else
+		    replacement = bfd_get_filename (needed.by);
+
 		  if (replacement)
 		    {
 		      char * slash;
@@ -582,7 +597,7 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	      break;
 
 	    case 'L':
-	      if (strcmp (var + 2, "IB") == 0)
+	      if (strcmp (v, "IB") == 0 || strcmp (v, "IB}") == 0)
 		{
 		  /* LIB - replace with "lib" in 32-bit environments
 		     and "lib64" in 64-bit environments.  */
@@ -603,17 +618,12 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	      break;
 
 	    case 'P':
-	      if (strcmp (var + 2, "LATFORM") == 0)
-		{
-		  /* Supporting $PLATFORM in a cross-hosted environment is not
-		     possible.  Supporting it in a native environment involves
-		     loading the <sys/auxv.h> header file which loads the
-		     system <elf.h> header file, which conflicts with the
-		     "include/elf/mips.h" header file.  */
-		  replacement = NULL;
-		}
-	      break;
-
+	      /* Supporting $PLATFORM in a cross-hosted environment is not
+		 possible.  Supporting it in a native environment involves
+		 loading the <sys/auxv.h> header file which loads the
+		 system <elf.h> header file, which conflicts with the
+		 "include/elf/mips.h" header file.  */
+	      /* Fall through.  */
 	    default:
 	      break;
 	    }
@@ -623,14 +633,20 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	      char * filename2 = xmalloc (flen + strlen (replacement));
 
 	      if (end)
-		sprintf (filename2, "%.*s%s/%s",
-			 (int)(var - filename), filename,
-			 replacement, end + 1);
+		{
+		  sprintf (filename2, "%.*s%s/%s",
+			   (int)(var - filename), filename,
+			   replacement, end + 1);
+		  offset = (var - filename) + 1 + strlen (replacement);
+		}
 	      else
-		sprintf (filename2, "%.*s%s",
-			 (int)(var - filename), filename,
-			 replacement);
-		
+		{
+		  sprintf (filename2, "%.*s%s",
+			   (int)(var - filename), filename,
+			   replacement);
+		  offset = var - filename + strlen (replacement);
+		}
+
 	      free (filename);
 	      filename = filename2;
 	      /* There is no need to restore the path separator (when
@@ -647,12 +663,17 @@ gld${EMULATION_NAME}_search_needed (const char *path,
 	      if (end)
 		/* Restore the path separator.  */
 		* end = '/';
+
+	      /* PR 20784: Make sure that we resume the scan
+	         *after* the token that we could not replace.  */
+	      offset = (var + 1) - filename;
 	    }
 
 	  free (freeme);
 	}
 
       needed.name = filename;
+
       if (gld${EMULATION_NAME}_try_needed (&needed, force))
 	return TRUE;
 
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 698d366..d4f33b7 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1865,6 +1865,16 @@ specifies the first set of directories to search.  The
 either by specifying a list of names separated by colons, or by
 appearing multiple times.
 
+The tokens @var{$ORIGIN} and @var{$LIB} can appear in these search
+directories.  They will be replaced by the full path to the directory
+containing the program or shared object in the case of @var{$ORIGIN}
+and either @samp{lib} - for 32-bit binaries - or @samp{lib64} - for
+64-bit binaries - in the case of @var{$LIB}.
+
+The alternative form of these tokens - @var{$@{ORIGIN@}} and
+@var{$@{LIB@}} can also be used.  The token @var{$PLATFORM} is not
+supported.
+
 This option should be used with caution as it overrides the search path
 that may have been hard compiled into a shared library. In such a case it
 is possible to use unintentionally a different search path than the


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