canonicalize: don't lose errno
authorEric Blake <ebb9@byu.net>
Wed, 16 Sep 2009 19:51:50 +0000 (13:51 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 18 Sep 2009 01:16:15 +0000 (19:16 -0600)
canonicalize-lgpl was already immune; glibc has the same bug:
http://sources.redhat.com/bugzilla/show_bug.cgi?id=10635

* lib/canonicalize.c (canonicalize_filename_mode): Protect errno
over calls to free.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/canonicalize.c

index 33507bb..b078c1b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2009-09-17  Eric Blake  <ebb9@byu.net>
 
+       canonicalize: don't lose errno
+       * lib/canonicalize.c (canonicalize_filename_mode): Protect errno
+       over calls to free.
+
        canonicalize: simplify errno handling
        * lib/canonicalize.c (__set_errno): Delete macro, and use direct
        assignment.
index c0a814d..402a8ff 100644 (file)
@@ -152,6 +152,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
   char const *rname_limit;
   size_t extra_len = 0;
   Hash_table *ht = NULL;
+  int saved_errno;
 
   if (name == NULL)
     {
@@ -239,6 +240,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
 
          if (lstat (rname, &st) != 0)
            {
+             saved_errno = errno;
              if (can_mode == CAN_EXISTING)
                goto error;
              if (can_mode == CAN_ALL_BUT_LAST && *end)
@@ -259,7 +261,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
                {
                  if (can_mode == CAN_MISSING)
                    continue;
-                 errno = ELOOP;
+                 saved_errno = ELOOP;
                  goto error;
                }
 
@@ -268,6 +270,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
                {
                  if (can_mode == CAN_MISSING && errno != ENOMEM)
                    continue;
+                 saved_errno = errno;
                  goto error;
                }
 
@@ -303,7 +306,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode)
            {
              if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
                {
-                 errno = ENOTDIR;
+                 saved_errno = ENOTDIR;
                  goto error;
                }
            }
@@ -323,5 +326,6 @@ error:
   free (rname);
   if (ht)
     hash_free (ht);
+  errno = saved_errno;
   return NULL;
 }