From e680a6b69b4bd173a180419e973a9bf18a000151 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 7 Nov 2016 15:05:34 +0000 Subject: [PATCH] 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. --- 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 + 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 + * 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 header file which loads the - system 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 header file which loads the + system 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 -- 2.7.4