bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

coreutils-5.0: bugs in readlink --canonicalize


From: Jim Meyering
Subject: coreutils-5.0: bugs in readlink --canonicalize
Date: Thu, 10 Apr 2003 19:22:45 +0200

`readlink --canonicalize' (aka lib/canonicalize.c) had problems
on e.g., Solaris systems.  This affects only systems that lack
canonicalize_file_name and that have the resolvepath function,
like Solaris.  Here are examples of how it fails:

  $ readlink --canonical .
  [Exit 1]
  $ readlink --canonical /no-such-file
  readlink: memory exhausted
  [Exit 1]
  $ readlink --canonical /
  /cÈ

Note that in the last example above, there are two extra bytes
after the `/'.

Although df.c also uses canonicalize_file_name, it's not affected.

Here's the fix:

        * canonicalize.c (canonicalize_file_name) [HAVE_RESOLVEPATH]: Remove
        stray semicolon that caused `readlink --canonical RELATIVE_NAME' to
        fail on e.g., Solaris systems.  Reported by Bruce Korb.
        (canonicalize_file_name): Return NULL immediately if resolvepath fails.
        Otherwise, `readlink --canonical /no-such-file' would exhaust
        virtual memory on some systems (e.g. Solaris).
        (canonicalize_file_name): Always free `extra_buf' before returning.
        (canonicalize_file_name): NUL-terminate the result.

Yes, I'll be adding a few tests, soon :-)

Index: lib/canonicalize.c
===================================================================
RCS file: /fetish/cu/lib/canonicalize.c,v
retrieving revision 1.3
retrieving revision 1.7
diff -u -p -u -p -r1.3 -r1.7
--- lib/canonicalize.c  20 Jan 2003 16:41:19 -0000      1.3
+++ lib/canonicalize.c  10 Apr 2003 17:03:26 -0000      1.7
@@ -130,7 +130,7 @@ canonicalize_file_name (const char *name
     {
       char *wd;
 
-      if (!(wd = xgetcwd ()));
+      if (!(wd = xgetcwd ()))
        return NULL;
 
       extra_buf = path_concat (wd, name, NULL);
@@ -147,18 +147,22 @@ canonicalize_file_name (const char *name
       resolved_size = 2 * resolved_size + 1;
       resolved = xmalloc (resolved_size);
       resolved_len = resolvepath (name, resolved, resolved_size);
+      if (resolved_len < 0)
+       {
+         free (resolved);
+         free (extra_buf);
+         return NULL;
+       }
       if (resolved_len < resolved_size)
        break;
       free (resolved);
     }
 
-  if (resolved_len < 0)
-    {
-      free (resolved);
-      resolved = NULL;
-    }
-
   free (extra_buf);
+
+  /* NUL-terminate the resulting name.  */
+  resolved[resolved_len] = '\0';
+
   return resolved;
 
 #else /* !HAVE_RESOLVEPATH */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]