I've noticed some behavior with make_relative_prefix that surprised
me.  In particular, consider this program:

  #include <stdio.h>

  extern char * make_relative_prefix (const char *progname,
                                      const char *bin_prefix,
                                      const char *prefix);

  int main () {
    char *reloc;

    reloc = make_relative_prefix ("/some/where/include/c++/4.2",
                                  "/opt/foo/include/c++/4.2",
                                  "/opt/foo");
    printf ("%s\n", reloc);
  }

I expected it to print:

  /some/where/../../..

but, instead, it prints:

  /some/where/include/c++/../../../../foo

It treats only "/opt" as a common component of the two paths, rathe
than "/opt/foo".  If you use "/opt/foo/" (instead of "/opt/foo") for
the last argument, the answer is as I expected.  This seems odd to me;
is it the intended behavior?

The patch below (which is against an older version of libiberty, and
might need updating) fixes it.  Assuming you agree that this is a bug,
would this patch (with updating and testing) be OK?

Thanks,

--
Mark Mitchell
CodeSourcery
[EMAIL PROTECTED]
(650) 331-3385 x713

Index: libiberty/make-relative-prefix.c
===================================================================
--- libiberty/make-relative-prefix.c    (revision 165621)
+++ libiberty/make-relative-prefix.c    (working copy)
@@ -340,7 +340,23 @@ make_relative_prefix (const char *progna
   n = (prefix_num < bin_num) ? prefix_num : bin_num;
   for (common = 0; common < n; common++)
     {
-      if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
+      const char *bin_dir;
+      const char *prefix_dir;
+      size_t bin_len;
+      size_t prefix_len;
+
+      /* Strip any trailing directory separators from the directories
+        before comparing them.  */
+      bin_dir = bin_dirs[common];
+      bin_len = strlen (bin_dir);
+      if (IS_DIR_SEPARATOR (bin_dir[bin_len - 1]))
+       --bin_len;
+      prefix_dir = prefix_dirs[common];
+      prefix_len = strlen (prefix_dir);
+      if (IS_DIR_SEPARATOR (prefix_dir[prefix_len - 1]))
+       --prefix_len;
+      if (strncmp (bin_dir, prefix_dir, 
+                  (bin_len > prefix_len) ? bin_len : prefix_len) != 0)
        break;
     }
 

Reply via email to