From patchwork Wed Feb 19 21:03:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Eggert X-Patchwork-Id: 38246 Received: (qmail 100550 invoked by alias); 19 Feb 2020 21:03:47 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 100542 invoked by uid 89); 19 Feb 2020 21:03:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-15.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=H*MI:edu, H*m:edu, timestamp, 1876 X-HELO: zimbra.cs.ucla.edu From: Paul Eggert To: libc-alpha@sourceware.org Cc: Paul Eggert Subject: [PATCH] Speed up realpath and fix EOVERFLOW bug Date: Wed, 19 Feb 2020 13:03:39 -0800 Message-Id: <20200219210339.173576-1-eggert@cs.ucla.edu> MIME-Version: 1.0 [BZ#24970] * stdlib/canonicalize.c: Do not include ; no longer needed. (__realpath): Use __readlink instead of __lxstat64 to determine whether RPATH is a symbolic link. This avoids an unnecessary __lxstat64 when RPATH is a symbolic link and replaces __lxstat64 with __readlink when RPATH is not a symbolic link. It also avoids an unnecessary failure if __lxstat64 would fail with errno == EOVERFLOW due to timestamp or other integer overflow. Remove unnecessary S_ISDIR check, as the next time through the loop will fail with errno == ENOTDIR as appropriate. --- stdlib/canonicalize.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c index cbd885a3c5..cd2051d35f 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -98,9 +97,10 @@ __realpath (const char *name, char *resolved) dest = rpath + 1; } + char *buf = __alloca (path_max); + for (start = end = name; *start; start = end) { - struct stat64 st; int n; /* Skip sequence of multiple path-separators. */ @@ -158,12 +158,14 @@ __realpath (const char *name, char *resolved) dest = __mempcpy (dest, start, end - start); *dest = '\0'; - if (__lxstat64 (_STAT_VER, rpath, &st) < 0) - goto error; - - if (S_ISLNK (st.st_mode)) + n = __readlink (rpath, buf, path_max); + if (n < 0) + { + if (errno != EINVAL) + goto error; + } + else { - char *buf = __alloca (path_max); size_t len; if (++num_links > __eloop_threshold ()) @@ -172,11 +174,6 @@ __realpath (const char *name, char *resolved) goto error; } - n = __readlink (rpath, buf, path_max - 1); - if (n < 0) - goto error; - buf[n] = '\0'; - if (!extra_buf) extra_buf = __alloca (path_max); @@ -187,6 +184,8 @@ __realpath (const char *name, char *resolved) goto error; } + buf[n] = '\0'; + /* Careful here, end may be a pointer into extra_buf... */ memmove (&extra_buf[n], end, len + 1); name = end = memcpy (extra_buf, buf, n); @@ -198,11 +197,6 @@ __realpath (const char *name, char *resolved) if (dest > rpath + 1) while ((--dest)[-1] != '/'); } - else if (!S_ISDIR (st.st_mode) && *end != '\0') - { - __set_errno (ENOTDIR); - goto error; - } } } if (dest > rpath + 1 && dest[-1] == '/')