On 2020-03-07 I wrote: > 2020-03-07 Bruno Haible <br...@clisp.org> > > findprog, relocatable-prog: Ignore directories during PATH search. > Reported by Frederick Eaton via Dmitry Goncharov in > <https://lists.gnu.org/archive/html/bug-gnulib/2020-03/msg00003.html>. > * lib/findprog.c (find_in_path): When the file found in a PATH element > is a directory, continue searching. > * lib/progreloc.c (maybe_executable): Likewise.
Oops, this patch patch was incomplete. Includes and module description updates were missing. I had to revert it. Now I'm committing a completed variant. 2020-04-10 Bruno Haible <br...@clisp.org> findprog, relocatable-prog: Ignore directories during PATH search. Reported by Frederick Eaton via Dmitry Goncharov in <https://lists.gnu.org/archive/html/bug-gnulib/2020-03/msg00003.html>. * lib/findprog.c (find_in_path): When the file found in a PATH element is a directory, continue searching. * modules/findprog (Depends-on): Add sys_stat, stat. * modules/findprog-lgpl (Depends-on): Likewise. * lib/progreloc.c (maybe_executable): When the file found in a PATH element is a directory, continue searching. * lib/relocwrapper.c: Update comments. * modules/relocatable-prog-wrapper (Files): Add m4/largefile.m4. (configure.ac-early): New section. diff --git a/lib/findprog.c b/lib/findprog.c index d0d4179..b562e9d 100644 --- a/lib/findprog.c +++ b/lib/findprog.c @@ -25,6 +25,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#if !(defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__) +# include <sys/stat.h> +#endif /* Avoid collision between findprog.c and findprog-lgpl.c. */ #if IN_FINDPROG_LGPL || ! GNULIB_FINDPROG_LGPL @@ -105,22 +108,29 @@ find_in_path (const char *progname) design flaw. */ if (eaccess (progpathname, X_OK) == 0) { - /* Found! */ - if (strcmp (progpathname, progname) == 0) + /* Check that the progpathname does not point to a directory. */ + struct stat statbuf; + + if (stat (progpathname, &statbuf) >= 0 + && ! S_ISDIR (statbuf.st_mode)) { - free (progpathname); - - /* Add the "./" prefix for real, that xconcatenated_filename() - optimized away. This avoids a second PATH search when the - caller uses execlp/execvp. */ - progpathname = XNMALLOC (2 + strlen (progname) + 1, char); - progpathname[0] = '.'; - progpathname[1] = '/'; - memcpy (progpathname + 2, progname, strlen (progname) + 1); + /* Found! */ + if (strcmp (progpathname, progname) == 0) + { + free (progpathname); + + /* Add the "./" prefix for real, that xconcatenated_filename() + optimized away. This avoids a second PATH search when the + caller uses execlp/execvp. */ + progpathname = XNMALLOC (2 + strlen (progname) + 1, char); + progpathname[0] = '.'; + progpathname[1] = '/'; + memcpy (progpathname + 2, progname, strlen (progname) + 1); + } + + free (path); + return progpathname; } - - free (path); - return progpathname; } free (progpathname); diff --git a/lib/progreloc.c b/lib/progreloc.c index b555211..45be1ca 100644 --- a/lib/progreloc.c +++ b/lib/progreloc.c @@ -154,7 +154,7 @@ static int executable_fd = -1; /* Define this function only when it's needed. */ #if !(defined WINDOWS_NATIVE || defined __EMX__) -/* Tests whether a given pathname may belong to the executable. */ +/* Tests whether a given filename may belong to the executable. */ static bool maybe_executable (const char *filename) { @@ -173,18 +173,20 @@ maybe_executable (const char *filename) struct stat statfile; if (fstat (executable_fd, &statexe) >= 0) - { - if (stat (filename, &statfile) < 0) - return false; - if (!(statfile.st_dev + return (stat (filename, &statfile) >= 0 + && statfile.st_dev && statfile.st_dev == statexe.st_dev - && statfile.st_ino == statexe.st_ino)) - return false; - } + && statfile.st_ino == statexe.st_ino); } # endif - return true; + /* Check that the filename does not point to a directory. */ + { + struct stat statfile; + + return (stat (filename, &statfile) >= 0 + && ! S_ISDIR (statfile.st_mode)); + } } #endif diff --git a/lib/relocwrapper.c b/lib/relocwrapper.c index dfe7e4f..e3dc197 100644 --- a/lib/relocwrapper.c +++ b/lib/relocwrapper.c @@ -19,14 +19,15 @@ relocwrapper -> progname -> progreloc + -> stat + -> filename + -> pathmax + -> verify -> areadlink -> careadlinkat -> allocator -> readlink -> stat - -> filename - -> pathmax - -> verify -> canonicalize-lgpl -> filename -> malloca diff --git a/modules/findprog b/modules/findprog index d48158b..b5f3c20 100644 --- a/modules/findprog +++ b/modules/findprog @@ -9,9 +9,11 @@ m4/eaccess.m4 Depends-on: stdbool +sys_stat xalloc xconcat-filename access +stat unistd configure.ac: diff --git a/modules/findprog-lgpl b/modules/findprog-lgpl index 477eccb..3c56f02 100644 --- a/modules/findprog-lgpl +++ b/modules/findprog-lgpl @@ -10,9 +10,11 @@ m4/eaccess.m4 Depends-on: stdbool +sys_stat strdup concat-filename access +stat unistd configure.ac: diff --git a/modules/relocatable-prog-wrapper b/modules/relocatable-prog-wrapper index 3cc3d76..f97fdae 100644 --- a/modules/relocatable-prog-wrapper +++ b/modules/relocatable-prog-wrapper @@ -25,6 +25,7 @@ lib/relocatable.c lib/setenv.c lib/c-ctype.h lib/c-ctype.c +m4/largefile.m4 m4/malloca.m4 m4/canonicalize.m4 m4/eealloc.m4 @@ -50,6 +51,9 @@ string verify xalloc-oversized +configure.ac-early: +AC_REQUIRE([AC_SYS_LARGEFILE]) + configure.ac: AC_REQUIRE([AC_C_RESTRICT]) gl_FUNC_READLINK_SEPARATE