From 5f9f31ad129d97e6fc548954c9b97e27dd332600 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Mon, 18 Sep 2017 09:26:00 -0300 Subject: [PATCH] scratch_buffer: use union for internal buffer Problem reported by Florian Weimer [1] and solution suggested by Andreas Schwab [2]. It also set the same buffer size independent of architecture max_align_t size. Checked on x86_64-linux-gnu and i686-linux-gnu. * lib/malloc/scratch_buffer.h (struct scratch_buffer): Use an union instead of a max_align_t array for __space, so that __space is the same size on all platforms. * malloc/scratch_buffer_grow_preserve.c (__libc_scratch_buffer_grow_preserve): Likewise. [1] https://sourceware.org/ml/libc-alpha/2017-09/msg00693.html [2] https://sourceware.org/ml/libc-alpha/2017-09/msg00695.html --- ChangeLog | 6 ++++++ include/scratch_buffer.h | 6 +++--- malloc/scratch_buffer_grow_preserve.c | 4 ++-- malloc/tst-scratch_buffer.c | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 416d673523..67394882e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2017-09-25 Adhemerval Zanella + * lib/malloc/scratch_buffer.h (struct scratch_buffer): + Use an union instead of a max_align_t array for __space, + so that __space is the same size on all platforms. + * malloc/scratch_buffer_grow_preserve.c + (__libc_scratch_buffer_grow_preserve): Likewise. + [BZ #22183] * include/gnu-versions.h (_GNU_GLOB_INTERFACE_VERSION): Increase version to 2. diff --git a/include/scratch_buffer.h b/include/scratch_buffer.h index bb04662eb2..b19b166080 100644 --- a/include/scratch_buffer.h +++ b/include/scratch_buffer.h @@ -66,7 +66,7 @@ struct scratch_buffer { void *data; /* Pointer to the beginning of the scratch area. */ size_t length; /* Allocated space at the data pointer, in bytes. */ - max_align_t __space[(1023 + sizeof (max_align_t)) / sizeof (max_align_t)]; + union { max_align_t __align; char __c[1024]; } __space; }; /* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space @@ -74,7 +74,7 @@ struct scratch_buffer { static inline void scratch_buffer_init (struct scratch_buffer *buffer) { - buffer->data = buffer->__space; + buffer->data = buffer->__space.__c; buffer->length = sizeof (buffer->__space); } @@ -82,7 +82,7 @@ scratch_buffer_init (struct scratch_buffer *buffer) static inline void scratch_buffer_free (struct scratch_buffer *buffer) { - if (buffer->data != buffer->__space) + if (buffer->data != buffer->__space.__c) free (buffer->data); } diff --git a/malloc/scratch_buffer_grow_preserve.c b/malloc/scratch_buffer_grow_preserve.c index 9268615311..59a922b8a9 100644 --- a/malloc/scratch_buffer_grow_preserve.c +++ b/malloc/scratch_buffer_grow_preserve.c @@ -30,14 +30,14 @@ __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer) size_t new_length = 2 * buffer->length; void *new_ptr; - if (buffer->data == buffer->__space) + if (buffer->data == buffer->__space.__c) { /* Move buffer to the heap. No overflow is possible because buffer->length describes a small buffer on the stack. */ new_ptr = malloc (new_length); if (new_ptr == NULL) return false; - memcpy (new_ptr, buffer->__space, buffer->length); + memcpy (new_ptr, buffer->__space.__c, buffer->length); } else { diff --git a/malloc/tst-scratch_buffer.c b/malloc/tst-scratch_buffer.c index 5c9f3442ae..86447b6230 100644 --- a/malloc/tst-scratch_buffer.c +++ b/malloc/tst-scratch_buffer.c @@ -59,7 +59,7 @@ array_size_must_fail (size_t a, size_t b) pass, a, b); return false; } - if (buf.data != buf.__space) + if (buf.data != buf.__space.__c) { printf ("scratch_buffer_set_array_size did not free: %d %zu %zu\n", pass, a, b);