This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCHv2 2/2] realpath: don't lose errno on failure


Part 2 of fixes for BZ #10635.

While glibc tries hard to make free() not clobber errno, this
is not (yet) a POSIX requirement, and users may provide alternative
malloc implementations where free does clobber errno.  Therefore,
we must ensure the correct error no matter how realpath() fails.

* stdlib/canonicalize.c (__realpath): Avoid clobbering errno
during free.
---
 ChangeLog             |  6 ++++++
 NEWS                  | 10 +++++-----
 stdlib/canonicalize.c | 26 +++++++++++++++++++-------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3336c10..62fa5f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-10-01  Eric Blake  <eblake@redhat.com>

+	[BZ #10635]
+	realpath: don't lose errno on failure
+	* stdlib/canonicalize.c (__realpath): Avoid clobbering errno
+	during free.
+	* NEWS: Mention it.
+
 	realpath: allow // to be handled specially
 	* stdlib/canonicalize.c (__realpath): Add and honor
 	DOUBLE_SLASH_IS_DISTINCT_ROOT.
diff --git a/NEWS b/NEWS
index f77d809..23000cf 100644
--- a/NEWS
+++ b/NEWS
@@ -9,11 +9,11 @@ Version 2.19

 * The following bugs are resolved with this release:

-  13985, 14155, 14547, 14699, 15048, 15400, 15427, 15522, 15531, 15532,
-  15608, 15609, 15610, 15640, 15681, 15736, 15748, 15749, 15754, 15760,
-  15797, 15844, 15849, 15855, 15856, 15857, 15859, 15867, 15886, 15887,
-  15890, 15892, 15893, 15895, 15897, 15905, 15909, 15919, 15921, 15923,
-  15939, 15963, 15966, 15988.
+  10635, 13985, 14155, 14547, 14699, 15048, 15400, 15427, 15522, 15531,
+  15532, 15608, 15609, 15610, 15640, 15681, 15736, 15748, 15749, 15754,
+  15760, 15797, 15844, 15849, 15855, 15856, 15857, 15859, 15867, 15886,
+  15887, 15890, 15892, 15893, 15895, 15897, 15905, 15909, 15919, 15921,
+  15923, 15939, 15963, 15966, 15988.

 * CVE-2012-4412 The strcoll implementation caches indices and rules for
   large collation sequences to optimize multiple passes.  This cache
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 5a52f06..ca2a1b5 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -51,6 +51,7 @@ __realpath (const char *name, char *resolved)
   const char *start, *end, *rpath_limit;
   long int path_max;
   int num_links = 0;
+  int saved_errno;

   if (name == NULL)
     {
@@ -93,6 +94,7 @@ __realpath (const char *name, char *resolved)
       if (!__getcwd (rpath, path_max))
 	{
 	  rpath[0] = '\0';
+	  saved_errno = errno;
 	  goto error;
 	}
       dest = __rawmemchr (rpath, '\0');
@@ -145,7 +147,7 @@ __realpath (const char *name, char *resolved)

 	      if (resolved)
 		{
-		  __set_errno (ENAMETOOLONG);
+		  saved_errno = ENAMETOOLONG;
 		  if (dest > rpath + 1)
 		    dest--;
 		  *dest = '\0';
@@ -158,7 +160,10 @@ __realpath (const char *name, char *resolved)
 		new_size += path_max;
 	      new_rpath = (char *) realloc (rpath, new_size);
 	      if (new_rpath == NULL)
-		goto error;
+		{
+		  saved_errno = ENOMEM;
+		  goto error;
+		}
 	      rpath = new_rpath;
 	      rpath_limit = rpath + new_size;

@@ -169,7 +174,10 @@ __realpath (const char *name, char *resolved)
 	  *dest = '\0';

 	  if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
-	    goto error;
+	    {
+	      saved_errno = errno;
+	      goto error;
+	    }

 	  if (S_ISLNK (st.st_mode))
 	    {
@@ -178,13 +186,16 @@ __realpath (const char *name, char *resolved)

 	      if (++num_links > __eloop_threshold ())
 		{
-		  __set_errno (ELOOP);
+		  saved_errno = ELOOP;
 		  goto error;
 		}

 	      n = __readlink (rpath, buf, path_max - 1);
 	      if (n < 0)
-		goto error;
+		{
+		  saved_errno = errno;
+		  goto error;
+		}
 	      buf[n] = '\0';

 	      if (!extra_buf)
@@ -193,7 +204,7 @@ __realpath (const char *name, char *resolved)
 	      len = strlen (end);
 	      if ((long int) (n + len) >= path_max)
 		{
-		  __set_errno (ENAMETOOLONG);
+		  saved_errno = ENAMETOOLONG;
 		  goto error;
 		}

@@ -220,7 +231,7 @@ __realpath (const char *name, char *resolved)
 	    }
 	  else if (!S_ISDIR (st.st_mode) && *end != '\0')
 	    {
-	      __set_errno (ENOTDIR);
+	      saved_errno = ENOTDIR;
 	      goto error;
 	    }
 	}
@@ -238,6 +249,7 @@ error:
   assert (resolved == NULL || resolved == rpath);
   if (resolved == NULL)
     free (rpath);
+  __set_errno (saved_errno);
   return NULL;
 }
 versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]