[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/6] canonicalize: fix EOVERFLOW bug
From: |
Paul Eggert |
Subject: |
[PATCH 2/6] canonicalize: fix EOVERFLOW bug |
Date: |
Wed, 2 Dec 2020 14:39:42 -0800 |
* lib/canonicalize.c (canonicalize_filename_mode):
When testing whether a directory entry is a symbolic link, or a
directory or other, do not use lstat or stat or
areadlink_with_size. Just use areadlink, as this suffices and it
avoids the EOVERFLOW problem that lstat and stat have.
* modules/canonicalize (Depends-on): Depend on areadlink instead
of areadlink-with-size and stat.
---
ChangeLog | 9 ++++++
lib/canonicalize.c | 67 +++++++++++++++++++-------------------------
modules/canonicalize | 3 +-
3 files changed, 39 insertions(+), 40 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 27afc2b4a..85f2c76a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2020-12-02 Paul Eggert <eggert@cs.ucla.edu>
+ canonicalize: fix EOVERFLOW bug
+ * lib/canonicalize.c (canonicalize_filename_mode):
+ When testing whether a directory entry is a symbolic link, or a
+ directory or other, do not use lstat or stat or
+ areadlink_with_size. Just use areadlink, as this suffices and it
+ avoids the EOVERFLOW problem that lstat and stat have.
+ * modules/canonicalize (Depends-on): Depend on areadlink instead
+ of areadlink-with-size and stat.
+
canonicalize-lgpl: fix EOVERFLOW bug
* lib/canonicalize-lgpl.c: Do not include <sys/stat.h>.
(__realpath): Do not use lstat. Just use readlink, as this
diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index 1fb3878ef..7b838e686 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -206,9 +206,7 @@ canonicalize_filename_mode (const char *name,
canonicalize_mode_t can_mode)
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
- if (end - start == 0)
- break;
- else if (end - start == 1 && start[0] == '.')
+ if (end - start == 1 && start[0] == '.')
/* nothing */;
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
@@ -222,8 +220,6 @@ canonicalize_filename_mode (const char *name,
canonicalize_mode_t can_mode)
}
else
{
- struct stat st;
-
if (!ISSLASH (dest[-1]))
*dest++ = '/';
@@ -246,31 +242,19 @@ canonicalize_filename_mode (const char *name,
canonicalize_mode_t can_mode)
dest += end - start;
*dest = '\0';
- if (logical && (can_mode == CAN_MISSING))
- {
- /* Avoid the stat in this case as it's inconsequential.
- i.e. we're neither resolving symlinks or testing
- component existence. */
- st.st_mode = 0;
- }
- else if ((logical ? stat (rname, &st) : lstat (rname, &st)) != 0)
+ char discard;
+ char *buf = logical ? NULL : areadlink (rname);
+ if (buf)
{
- /* FIXME: If errno == EOVERFLOW here, the entry exists. */
- saved_errno = errno;
- if (can_mode == CAN_EXISTING)
- goto error;
- if (can_mode == CAN_ALL_BUT_LAST)
+ /* A physical traversal and RNAME is a symbolic link. */
+ struct stat st;
+ if (lstat (rname, &st) != 0)
{
- if (end[strspn (end, SLASHES)] || saved_errno != ENOENT)
- goto error;
- continue;
+ saved_errno = errno;
+ free (buf);
+ goto error;
}
- st.st_mode = 0;
- }
- if (S_ISLNK (st.st_mode))
- {
- char *buf;
size_t n, len;
/* Detect loops. We cannot use the cycle-check module here,
@@ -282,15 +266,7 @@ canonicalize_filename_mode (const char *name,
canonicalize_mode_t can_mode)
if (can_mode == CAN_MISSING)
continue;
saved_errno = ELOOP;
- goto error;
- }
-
- buf = areadlink_with_size (rname, st.st_size);
- if (!buf)
- {
- if (can_mode == CAN_MISSING && errno != ENOMEM)
- continue;
- saved_errno = errno;
+ free (buf);
goto error;
}
@@ -344,11 +320,26 @@ canonicalize_filename_mode (const char *name,
canonicalize_mode_t can_mode)
free (buf);
}
- else
+ else if (can_mode != CAN_MISSING
+ && (!logical || readlink (rname, &discard, 1) < 0))
{
- if (!S_ISDIR (st.st_mode) && *end && (can_mode != CAN_MISSING))
+ saved_errno = errno;
+ switch (saved_errno)
{
- saved_errno = ENOTDIR;
+ case EINVAL:
+ /* RNAME exists and is not symbolic link. */
+ break;
+
+ case ENOENT:
+ /* RNAME does not exist. */
+ if (can_mode == CAN_EXISTING
+ || (can_mode == CAN_ALL_BUT_LAST
+ && end[strspn (end, SLASHES)]))
+ goto error;
+ break;
+
+ default:
+ /* Some other problem with RNAME. */
goto error;
}
}
diff --git a/modules/canonicalize b/modules/canonicalize
index 16dfb6999..a48d1930e 100644
--- a/modules/canonicalize
+++ b/modules/canonicalize
@@ -7,7 +7,7 @@ lib/canonicalize.c
m4/canonicalize.m4
Depends-on:
-areadlink-with-size
+areadlink
double-slash-root
errno
extensions
@@ -18,7 +18,6 @@ lstat
memmove
nocrash
pathmax
-stat
sys_stat
xalloc
xgetcwd
--
2.27.0
[PATCH 6/6] canonicalize: refactor can_mode flag, Paul Eggert, 2020/12/02
[PATCH 5/6] canonicalize: prefer signed integer types, Paul Eggert, 2020/12/02
Re: [PATCH 1/6] canonicalize-lgpl: fix EOVERFLOW bug, Adhemerval Zanella, 2020/12/11