Patchwork [Ada] Locate_Exec_On_Path should only return executable files

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 2, 2011, 3:25 p.m.
Message ID <20110802152540.GA11678@adacore.com>
Download mbox | patch
Permalink /patch/107947/
State New
Headers show

Comments

Arnaud Charlet - Aug. 2, 2011, 3:25 p.m.
When searching for an executable to run, Unix shells check every directory
on PATH and stop at the first matching executable found.
GNAT.OS_Lib.Locate_Exec_On_Path, however, returned the first matching
regular file, even if it wasn't executable. As a result, when an executable
tries to find where it is run from, we could end up with a discrepency.

To test the issue: create two directories bin1 and bin2. The first one
should contain a non-executable "exec" file, the second should contain
the result of compiling the following program. Add the directories in
that order on the PATH, and run "exec" from the command line. The Unix
shell will execute the one from bin2/ (since the one in bin1/ is not
executable), and the result of the execution should show that the file
was executed from bin2/

   with GNAT.OS_Lib;  use GNAT.OS_Lib;
   with Ada.Text_IO;  use Ada.Text_IO;
   procedure Exec is
   begin
      Put_Line ("Installed in " & Locate_Exec_On_Path ("exec").all);
   end Exec;

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-02  Emmanuel Briot  <briot@adacore.com>

	* adaint.c (__gnat_locate_exec_on_path): only returns executable
	files, not any regular file.
	(__gnat_locate_file_with_predicate): new subprogram.

Patch

Index: adaint.c
===================================================================
--- adaint.c	(revision 177121)
+++ adaint.c	(working copy)
@@ -2700,10 +2700,11 @@ 
   exit (status);
 }
 
-/* Locate a regular file, give a Path value.  */
+/* Locate file on path, that matches a predicate */
 
 char *
-__gnat_locate_regular_file (char *file_name, char *path_val)
+__gnat_locate_file_with_predicate
+   (char *file_name, char *path_val, int (*predicate)(char*))
 {
   char *ptr;
   char *file_path = (char *) alloca (strlen (file_name) + 1);
@@ -2733,7 +2734,7 @@ 
 
   if (absolute)
     {
-     if (__gnat_is_regular_file (file_path))
+     if (predicate (file_path))
        return xstrdup (file_path);
 
       return 0;
@@ -2746,7 +2747,7 @@ 
 
   if (*ptr != 0)
     {
-      if (__gnat_is_regular_file (file_name))
+      if (predicate (file_name))
         return xstrdup (file_name);
     }
 
@@ -2787,7 +2788,7 @@ 
 
       strcpy (++ptr, file_name);
 
-      if (__gnat_is_regular_file (file_path))
+      if (predicate (file_path))
         return xstrdup (file_path);
 
       if (*path_val == 0)
@@ -2802,6 +2803,24 @@ 
   return 0;
 }
 
+/* Locate an executable file, give a Path value.  */
+
+char *
+__gnat_locate_executable_file (char *file_name, char *path_val)
+{
+   return __gnat_locate_file_with_predicate
+      (file_name, path_val, &__gnat_is_executable_file);
+}
+
+/* Locate a regular file, give a Path value.  */
+
+char *
+__gnat_locate_regular_file (char *file_name, char *path_val)
+{
+   return __gnat_locate_file_with_predicate
+      (file_name, path_val, &__gnat_is_regular_file);
+}
+
 /* Locate an executable given a Path argument. This routine is only used by
    gnatbl and should not be used otherwise.  Use locate_exec_on_path
    instead.  */
@@ -2818,14 +2837,14 @@ 
 
       strcpy (full_exec_name, exec_name);
       strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
-      ptr = __gnat_locate_regular_file (full_exec_name, path_val);
+      ptr = __gnat_locate_executable_file (full_exec_name, path_val);
 
       if (ptr == 0)
-         return __gnat_locate_regular_file (exec_name, path_val);
+         return __gnat_locate_executable_file (exec_name, path_val);
       return ptr;
     }
   else
-    return __gnat_locate_regular_file (exec_name, path_val);
+    return __gnat_locate_executable_file (exec_name, path_val);
 }
 
 /* Locate an executable using the Systems default PATH.  */