This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCHv2 2/2] realpath: don't lose errno on failure
- From: Eric Blake <eblake at redhat dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 1 Oct 2013 14:22:54 -0600
- Subject: [PATCHv2 2/2] realpath: don't lose errno on failure
- Authentication-results: sourceware.org; auth=none
- References: <1380658974-28848-1-git-send-email-eblake at redhat dot com>
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