[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] careadlinkat: fix GCC 10 workaround
From: |
Paul Eggert |
Subject: |
[PATCH] careadlinkat: fix GCC 10 workaround |
Date: |
Mon, 11 May 2020 10:47:43 -0700 |
* lib/careadlinkat.c (careadlinkat) [GCC_LINT]:
Massage the code so that it’s closer to what it was before
the GCC 10.1.0 workaround was introduced. This fixes
a loop when !buffer and the bug workaround is in effect.
Remove unnecessary casts. Defend in a different way
against (buffer && !buffer_size), by adding at least 1
to buf_size each time through the loop.
---
ChangeLog | 11 +++++++++++
lib/careadlinkat.c | 38 +++++++++++++++++++-------------------
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index e7010b117..58a7a67dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2020-05-11 Paul Eggert <address@hidden>
+
+ careadlinkat: fix GCC 10 workaround
+ * lib/careadlinkat.c (careadlinkat) [GCC_LINT]:
+ Massage the code so that it’s closer to what it was before
+ the GCC 10.1.0 workaround was introduced. This fixes
+ a loop when !buffer and the bug workaround is in effect.
+ Remove unnecessary casts. Defend in a different way
+ against (buffer && !buffer_size), by adding at least 1
+ to buf_size each time through the loop.
+
2020-05-10 Bruno Haible <address@hidden>
doc: Mark HP-UX as unsupported.
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index fbed634f9..1aa04363d 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -70,39 +70,40 @@ careadlinkat (int fd, char const *filename,
size_t buf_size;
size_t buf_size_max =
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+ char stack_buf[1024];
#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1)
/* Pacify preadlinkat without creating a pointer to the stack
that a broken gcc -Wreturn-local-addr would cry wolf about. See:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95044
- This workaround differs substantially from the mainline code, but
+ This workaround differs from the mainline code, but
no other way to pacify GCC 10.1.0 is known; even an explicit
#pragma does not pacify GCC. When the GCC bug is fixed this
workaround should be limited to the broken GCC versions. */
- static char initial_buf[1];
- enum { initial_buf_size = 0 }; /* 0 so that initial_buf never changes. */
-#else
- char initial_buf[1024];
- enum { initial_buf_size = sizeof initial_buf };
+# define WORK_AROUND_GCC_BUG_95044
#endif
if (! alloc)
alloc = &stdlib_allocator;
- if (! buffer_size)
+ if (!buffer)
{
- /* Allocate the initial buffer. This way, in the common case of
- a symlink of small size without GCC_LINT, we get away with a
+#ifdef WORK_AROUND_GCC_BUG_95044
+ buffer = alloc->allocate (sizeof stack_buf);
+#else
+ /* Allocate the initial buffer on the stack. This way, in the
+ common case of a symlink of small size, we get away with a
single small malloc() instead of a big malloc() followed by a
shrinking realloc(). */
- buffer = initial_buf;
- buffer_size = initial_buf_size;
+ buffer = stack_buf;
+#endif
+ buffer_size = sizeof stack_buf;
}
buf = buffer;
buf_size = buffer_size;
- do
+ while (buf)
{
/* Attempt to read the link into the current buffer. */
ssize_t link_length = preadlinkat (fd, filename, buf, buf_size);
@@ -129,9 +130,9 @@ careadlinkat (int fd, char const *filename,
{
buf[link_size++] = '\0';
- if (buf == initial_buf)
+ if (buf == stack_buf)
{
- char *b = (char *) alloc->allocate (link_size);
+ char *b = alloc->allocate (link_size);
buf_size = link_size;
if (! b)
break;
@@ -141,7 +142,7 @@ careadlinkat (int fd, char const *filename,
if (link_size < buf_size && buf != buffer && alloc->reallocate)
{
/* Shrink BUF before returning it. */
- char *b = (char *) alloc->reallocate (buf, link_size);
+ char *b = alloc->reallocate (buf, link_size);
if (b)
return b;
}
@@ -152,8 +153,8 @@ careadlinkat (int fd, char const *filename,
if (buf != buffer)
alloc->free (buf);
- if (buf_size <= buf_size_max / 2)
- buf_size *= 2;
+ if (buf_size < buf_size_max / 2)
+ buf_size = 2 * buf_size + 1;
else if (buf_size < buf_size_max)
buf_size = buf_size_max;
else if (buf_size_max < SIZE_MAX)
@@ -163,9 +164,8 @@ careadlinkat (int fd, char const *filename,
}
else
break;
- buf = (char *) alloc->allocate (buf_size);
+ buf = alloc->allocate (buf_size);
}
- while (buf);
if (alloc->die)
alloc->die (buf_size);
--
2.17.1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] careadlinkat: fix GCC 10 workaround,
Paul Eggert <=