1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-06-13 19:21:36 +03:00

malloc: Sync dynarray with gnulib

It syncs with gnulib version a8bac4d49.  The main changes are:

  - Remove the usage of anonymous union within DYNARRAY_STRUCT.
  - Use DYNARRAY_FREE instead of DYNARRAY_NAME (free) so that
    Gnulib does not change 'free' to 'rpl_free'.
  - Use __nonnull instead of __attribute__ ((nonnull ())).
  - Use __attribute_maybe_unused__ instead of
    __attribute__ ((unused, nonnull (1))).
  - Use of _Noreturn instead of _attribute__ ((noreturn)).

The only difference with gnulib is:

--- glibc
+++ gnulib
@@ -18,6 +18,7 @@

 #include <dynarray.h>
 #include <stdio.h>
+#include <stdlib.h>

 void
 __libc_dynarray_at_failure (size_t size, size_t index)
@@ -27,7 +28,6 @@
   __snprintf (buf, sizeof (buf), "Fatal glibc error: "
               "array index %zu not less than array length %zu\n",
               index, size);
- __libc_fatal (buf);
 #else
  abort ();
 #endif

It seems a wrong sync from gnulib (the code is used on loader and
thus it requires __libc_fatal instead of abort).

Checked on x86_64-linux-gnu.
This commit is contained in:
Adhemerval Zanella
2021-01-11 12:03:38 -03:00
parent c8ba52ab33
commit de0e1b45b0
9 changed files with 95 additions and 84 deletions

View File

@ -135,7 +135,7 @@ struct DYNARRAY_STRUCT
size_t allocated; size_t allocated;
DYNARRAY_ELEMENT *array; DYNARRAY_ELEMENT *array;
} dynarray_header; } dynarray_header;
}; } u;
#if DYNARRAY_HAVE_SCRATCH #if DYNARRAY_HAVE_SCRATCH
/* Initial inline allocation. */ /* Initial inline allocation. */
@ -150,6 +150,10 @@ struct DYNARRAY_STRUCT
#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name) #define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name) #define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
so that Gnulib does not change 'free' to 'rpl_free'. */
#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
/* Address of the scratch buffer if any. */ /* Address of the scratch buffer if any. */
#if DYNARRAY_HAVE_SCRATCH #if DYNARRAY_HAVE_SCRATCH
# define DYNARRAY_SCRATCH(list) (list)->scratch # define DYNARRAY_SCRATCH(list) (list)->scratch
@ -177,10 +181,10 @@ static inline void
DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
{ {
#if DYNARRAY_HAVE_SCRATCH #if DYNARRAY_HAVE_SCRATCH
if (list->dynarray_header.array != list->scratch) if (list->u.dynarray_header.array != list->scratch)
free (list->dynarray_header.array); free (list->u.dynarray_header.array);
#else #else
free (list->dynarray_header.array); free (list->u.dynarray_header.array);
#endif #endif
} }
@ -188,86 +192,86 @@ DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
/* Initialize a dynamic array object. This must be called before any /* Initialize a dynamic array object. This must be called before any
use of the object. */ use of the object. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static void static void
DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
{ {
list->dynarray_header.used = 0; list->u.dynarray_header.used = 0;
list->dynarray_header.allocated = DYNARRAY_INITIAL_SIZE; list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
list->dynarray_header.array = DYNARRAY_SCRATCH (list); list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
} }
/* Deallocate the dynamic array and its elements. */ /* Deallocate the dynamic array and its elements. */
__attribute__ ((unused, nonnull (1))) __attribute_maybe_unused__ __nonnull ((1))
static void static void
DYNARRAY_NAME (free) (struct DYNARRAY_STRUCT *list) DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
{ {
DYNARRAY_NAME (free__elements__) DYNARRAY_NAME (free__elements__)
(list->dynarray_header.array, list->dynarray_header.used); (list->u.dynarray_header.array, list->u.dynarray_header.used);
DYNARRAY_NAME (free__array__) (list); DYNARRAY_NAME (free__array__) (list);
DYNARRAY_NAME (init) (list); DYNARRAY_NAME (init) (list);
} }
/* Return true if the dynamic array is in an error state. */ /* Return true if the dynamic array is in an error state. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static inline bool static inline bool
DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
{ {
return list->dynarray_header.allocated == __dynarray_error_marker (); return list->u.dynarray_header.allocated == __dynarray_error_marker ();
} }
/* Mark the dynamic array as failed. All elements are deallocated as /* Mark the dynamic array as failed. All elements are deallocated as
a side effect. */ a side effect. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static void static void
DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
{ {
DYNARRAY_NAME (free__elements__) DYNARRAY_NAME (free__elements__)
(list->dynarray_header.array, list->dynarray_header.used); (list->u.dynarray_header.array, list->u.dynarray_header.used);
DYNARRAY_NAME (free__array__) (list); DYNARRAY_NAME (free__array__) (list);
list->dynarray_header.array = DYNARRAY_SCRATCH (list); list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
list->dynarray_header.used = 0; list->u.dynarray_header.used = 0;
list->dynarray_header.allocated = __dynarray_error_marker (); list->u.dynarray_header.allocated = __dynarray_error_marker ();
} }
/* Return the number of elements which have been added to the dynamic /* Return the number of elements which have been added to the dynamic
array. */ array. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static inline size_t static inline size_t
DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
{ {
return list->dynarray_header.used; return list->u.dynarray_header.used;
} }
/* Return a pointer to the array element at INDEX. Terminate the /* Return a pointer to the array element at INDEX. Terminate the
process if INDEX is out of bounds. */ process if INDEX is out of bounds. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static inline DYNARRAY_ELEMENT * static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index) DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
{ {
if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list))) if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
__libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index); __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
return list->dynarray_header.array + index; return list->u.dynarray_header.array + index;
} }
/* Return a pointer to the first array element, if any. For a /* Return a pointer to the first array element, if any. For a
zero-length array, the pointer can be NULL even though the dynamic zero-length array, the pointer can be NULL even though the dynamic
array has not entered the failure state. */ array has not entered the failure state. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static inline DYNARRAY_ELEMENT * static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
{ {
return list->dynarray_header.array; return list->u.dynarray_header.array;
} }
/* Return a pointer one element past the last array element. For a /* Return a pointer one element past the last array element. For a
zero-length array, the pointer can be NULL even though the dynamic zero-length array, the pointer can be NULL even though the dynamic
array has not entered the failure state. */ array has not entered the failure state. */
__attribute__ ((nonnull (1))) __nonnull ((1))
static inline DYNARRAY_ELEMENT * static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
{ {
return list->dynarray_header.array + list->dynarray_header.used; return list->u.dynarray_header.array + list->u.dynarray_header.used;
} }
/* Internal function. Slow path for the add function below. */ /* Internal function. Slow path for the add function below. */
@ -275,7 +279,7 @@ static void
DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
{ {
if (__glibc_unlikely if (__glibc_unlikely
(!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract, (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list), DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT)))) sizeof (DYNARRAY_ELEMENT))))
{ {
@ -284,13 +288,13 @@ DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
} }
/* Copy the new element and increase the array length. */ /* Copy the new element and increase the array length. */
list->dynarray_header.array[list->dynarray_header.used++] = item; list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
} }
/* Add ITEM at the end of the array, enlarging it by one element. /* Add ITEM at the end of the array, enlarging it by one element.
Mark *LIST as failed if the dynamic array allocation size cannot be Mark *LIST as failed if the dynamic array allocation size cannot be
increased. */ increased. */
__attribute__ ((unused, nonnull (1))) __nonnull ((1))
static inline void static inline void
DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
{ {
@ -299,15 +303,15 @@ DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
return; return;
/* Enlarge the array if necessary. */ /* Enlarge the array if necessary. */
if (__glibc_unlikely (list->dynarray_header.used if (__glibc_unlikely (list->u.dynarray_header.used
== list->dynarray_header.allocated)) == list->u.dynarray_header.allocated))
{ {
DYNARRAY_NAME (add__) (list, item); DYNARRAY_NAME (add__) (list, item);
return; return;
} }
/* Copy the new element and increase the array length. */ /* Copy the new element and increase the array length. */
list->dynarray_header.array[list->dynarray_header.used++] = item; list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
} }
/* Internal function. Building block for the emplace functions below. /* Internal function. Building block for the emplace functions below.
@ -316,8 +320,8 @@ static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
{ {
DYNARRAY_ELEMENT *result DYNARRAY_ELEMENT *result
= &list->dynarray_header.array[list->dynarray_header.used]; = &list->u.dynarray_header.array[list->u.dynarray_header.used];
++list->dynarray_header.used; ++list->u.dynarray_header.used;
#if defined (DYNARRAY_ELEMENT_INIT) #if defined (DYNARRAY_ELEMENT_INIT)
DYNARRAY_ELEMENT_INIT (result); DYNARRAY_ELEMENT_INIT (result);
#elif defined (DYNARRAY_ELEMENT_FREE) #elif defined (DYNARRAY_ELEMENT_FREE)
@ -331,7 +335,7 @@ static DYNARRAY_ELEMENT *
DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
{ {
if (__glibc_unlikely if (__glibc_unlikely
(!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract, (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list), DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT)))) sizeof (DYNARRAY_ELEMENT))))
{ {
@ -344,7 +348,7 @@ DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
/* Allocate a place for a new element in *LIST and return a pointer to /* Allocate a place for a new element in *LIST and return a pointer to
it. The pointer can be NULL if the dynamic array cannot be it. The pointer can be NULL if the dynamic array cannot be
enlarged due to a memory allocation failure. */ enlarged due to a memory allocation failure. */
__attribute__ ((unused, warn_unused_result, nonnull (1))) __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
static static
/* Avoid inlining with the larger initialization code. */ /* Avoid inlining with the larger initialization code. */
#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE)) #if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
@ -358,8 +362,8 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
return NULL; return NULL;
/* Enlarge the array if necessary. */ /* Enlarge the array if necessary. */
if (__glibc_unlikely (list->dynarray_header.used if (__glibc_unlikely (list->u.dynarray_header.used
== list->dynarray_header.allocated)) == list->u.dynarray_header.allocated))
return (DYNARRAY_NAME (emplace__) (list)); return (DYNARRAY_NAME (emplace__) (list));
return DYNARRAY_NAME (emplace__tail__) (list); return DYNARRAY_NAME (emplace__tail__) (list);
} }
@ -368,32 +372,32 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
existing size, new elements are added (which can be initialized). existing size, new elements are added (which can be initialized).
Otherwise, the list is truncated, and elements are freed. Return Otherwise, the list is truncated, and elements are freed. Return
false on memory allocation failure (and mark *LIST as failed). */ false on memory allocation failure (and mark *LIST as failed). */
__attribute__ ((unused, nonnull (1))) __attribute_maybe_unused__ __nonnull ((1))
static bool static bool
DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size) DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
{ {
if (size > list->dynarray_header.used) if (size > list->u.dynarray_header.used)
{ {
bool ok; bool ok;
#if defined (DYNARRAY_ELEMENT_INIT) #if defined (DYNARRAY_ELEMENT_INIT)
/* The new elements have to be initialized. */ /* The new elements have to be initialized. */
size_t old_size = list->dynarray_header.used; size_t old_size = list->u.dynarray_header.used;
ok = __libc_dynarray_resize (&list->dynarray_abstract, ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
size, DYNARRAY_SCRATCH (list), size, DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT)); sizeof (DYNARRAY_ELEMENT));
if (ok) if (ok)
for (size_t i = old_size; i < size; ++i) for (size_t i = old_size; i < size; ++i)
{ {
DYNARRAY_ELEMENT_INIT (&list->dynarray_header.array[i]); DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
} }
#elif defined (DYNARRAY_ELEMENT_FREE) #elif defined (DYNARRAY_ELEMENT_FREE)
/* Zero initialization is needed so that the elements can be /* Zero initialization is needed so that the elements can be
safely freed. */ safely freed. */
ok = __libc_dynarray_resize_clear ok = __libc_dynarray_resize_clear
(&list->dynarray_abstract, size, (&list->u.dynarray_abstract, size,
DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT)); DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
#else #else
ok = __libc_dynarray_resize (&list->dynarray_abstract, ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
size, DYNARRAY_SCRATCH (list), size, DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT)); sizeof (DYNARRAY_ELEMENT));
#endif #endif
@ -405,40 +409,40 @@ DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
{ {
/* The list has shrunk in size. Free the removed elements. */ /* The list has shrunk in size. Free the removed elements. */
DYNARRAY_NAME (free__elements__) DYNARRAY_NAME (free__elements__)
(list->dynarray_header.array + size, (list->u.dynarray_header.array + size,
list->dynarray_header.used - size); list->u.dynarray_header.used - size);
list->dynarray_header.used = size; list->u.dynarray_header.used = size;
return true; return true;
} }
} }
/* Remove the last element of LIST if it is present. */ /* Remove the last element of LIST if it is present. */
__attribute__ ((unused, nonnull (1))) __attribute_maybe_unused__ __nonnull ((1))
static void static void
DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
{ {
/* used > 0 implies that the array is the non-failed state. */ /* used > 0 implies that the array is the non-failed state. */
if (list->dynarray_header.used > 0) if (list->u.dynarray_header.used > 0)
{ {
size_t new_length = list->dynarray_header.used - 1; size_t new_length = list->u.dynarray_header.used - 1;
#ifdef DYNARRAY_ELEMENT_FREE #ifdef DYNARRAY_ELEMENT_FREE
DYNARRAY_ELEMENT_FREE (&list->dynarray_header.array[new_length]); DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
#endif #endif
list->dynarray_header.used = new_length; list->u.dynarray_header.used = new_length;
} }
} }
/* Remove all elements from the list. The elements are freed, but the /* Remove all elements from the list. The elements are freed, but the
list itself is not. */ list itself is not. */
__attribute__ ((unused, nonnull (1))) __attribute_maybe_unused__ __nonnull ((1))
static void static void
DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list) DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
{ {
/* free__elements__ does nothing if the list is in the failed /* free__elements__ does nothing if the list is in the failed
state. */ state. */
DYNARRAY_NAME (free__elements__) DYNARRAY_NAME (free__elements__)
(list->dynarray_header.array, list->dynarray_header.used); (list->u.dynarray_header.array, list->u.dynarray_header.used);
list->dynarray_header.used = 0; list->u.dynarray_header.used = 0;
} }
#ifdef DYNARRAY_FINAL_TYPE #ifdef DYNARRAY_FINAL_TYPE
@ -448,13 +452,13 @@ DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
stored in *RESULT if LIST refers to an empty list. On success, the stored in *RESULT if LIST refers to an empty list. On success, the
pointer in *RESULT is heap-allocated and must be deallocated using pointer in *RESULT is heap-allocated and must be deallocated using
free. */ free. */
__attribute__ ((unused, warn_unused_result, nonnull (1, 2))) __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1, 2))
static bool static bool
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
DYNARRAY_FINAL_TYPE *result) DYNARRAY_FINAL_TYPE *result)
{ {
struct dynarray_finalize_result res; struct dynarray_finalize_result res;
if (__libc_dynarray_finalize (&list->dynarray_abstract, if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list), DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT), &res)) sizeof (DYNARRAY_ELEMENT), &res))
{ {
@ -466,7 +470,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
else else
{ {
/* On error, we need to free all data. */ /* On error, we need to free all data. */
DYNARRAY_NAME (free) (list); DYNARRAY_FREE (list);
errno = ENOMEM; errno = ENOMEM;
return false; return false;
} }
@ -479,12 +483,12 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
have a sentinel at the end). If LENGTHP is not NULL, the array have a sentinel at the end). If LENGTHP is not NULL, the array
length is written to *LENGTHP. *LIST is re-initialized and can be length is written to *LENGTHP. *LIST is re-initialized and can be
reused. */ reused. */
__attribute__ ((unused, warn_unused_result, nonnull (1))) __attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
static DYNARRAY_ELEMENT * static DYNARRAY_ELEMENT *
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp) DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
{ {
struct dynarray_finalize_result res; struct dynarray_finalize_result res;
if (__libc_dynarray_finalize (&list->dynarray_abstract, if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
DYNARRAY_SCRATCH (list), DYNARRAY_SCRATCH (list),
sizeof (DYNARRAY_ELEMENT), &res)) sizeof (DYNARRAY_ELEMENT), &res))
{ {
@ -497,7 +501,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
else else
{ {
/* On error, we need to free all data. */ /* On error, we need to free all data. */
DYNARRAY_NAME (free) (list); DYNARRAY_FREE (list);
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }

View File

@ -165,8 +165,7 @@ bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
/* Internal function. Terminate the process after an index error. /* Internal function. Terminate the process after an index error.
SIZE is the number of elements of the dynamic array. INDEX is the SIZE is the number of elements of the dynamic array. INDEX is the
lookup index which triggered the failure. */ lookup index which triggered the failure. */
void __libc_dynarray_at_failure (size_t size, size_t index) _Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
__attribute__ ((noreturn));
#ifndef _ISOMAC #ifndef _ISOMAC
libc_hidden_proto (__libc_dynarray_emplace_enlarge) libc_hidden_proto (__libc_dynarray_emplace_enlarge)

View File

@ -22,10 +22,14 @@
void void
__libc_dynarray_at_failure (size_t size, size_t index) __libc_dynarray_at_failure (size_t size, size_t index)
{ {
#ifdef _LIBC
char buf[200]; char buf[200];
__snprintf (buf, sizeof (buf), "Fatal glibc error: " __snprintf (buf, sizeof (buf), "Fatal glibc error: "
"array index %zu not less than array length %zu\n", "array index %zu not less than array length %zu\n",
index, size); index, size);
__libc_fatal (buf); __libc_fatal (buf);
#else
abort ();
#endif
} }
libc_hidden_def (__libc_dynarray_at_failure) libc_hidden_def (__libc_dynarray_at_failure)

View File

@ -18,6 +18,7 @@
#include <dynarray.h> #include <dynarray.h>
#include <errno.h> #include <errno.h>
#include <intprops.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -51,7 +52,7 @@ __libc_dynarray_emplace_enlarge (struct dynarray_header *list,
} }
size_t new_size; size_t new_size;
if (__builtin_mul_overflow (new_allocated, element_size, &new_size)) if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size))
return false; return false;
void *new_array; void *new_array;
if (list->array == scratch) if (list->array == scratch)

View File

@ -18,6 +18,7 @@
#include <dynarray.h> #include <dynarray.h>
#include <errno.h> #include <errno.h>
#include <intprops.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -37,7 +38,7 @@ __libc_dynarray_resize (struct dynarray_header *list, size_t size,
over-allocation here. */ over-allocation here. */
size_t new_size_bytes; size_t new_size_bytes;
if (__builtin_mul_overflow (size, element_size, &new_size_bytes)) if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes))
{ {
/* Overflow. */ /* Overflow. */
__set_errno (ENOMEM); __set_errno (ENOMEM);

View File

@ -17,7 +17,6 @@
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <dynarray.h> #include <dynarray.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
bool bool
@ -28,7 +27,8 @@ __libc_dynarray_resize_clear (struct dynarray_header *list, size_t size,
if (!__libc_dynarray_resize (list, size, scratch, element_size)) if (!__libc_dynarray_resize (list, size, scratch, element_size))
return false; return false;
/* __libc_dynarray_resize already checked for overflow. */ /* __libc_dynarray_resize already checked for overflow. */
memset (list->array + (old_size * element_size), 0, char *array = list->array;
memset (array + (old_size * element_size), 0,
(size - old_size) * element_size); (size - old_size) * element_size);
return true; return true;
} }

View File

@ -249,9 +249,9 @@ test_str_fail (void)
else else
dynarray_str_free (&dyn); dynarray_str_free (&dyn);
TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch); TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0); TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0); TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
} }
/* Exercise failure in finalize. */ /* Exercise failure in finalize. */
@ -278,9 +278,9 @@ test_str_fail (void)
TEST_VERIFY_EXIT (result.array == (char **) (uintptr_t) -1); TEST_VERIFY_EXIT (result.array == (char **) (uintptr_t) -1);
TEST_VERIFY_EXIT (result.length == (size_t) -1); TEST_VERIFY_EXIT (result.length == (size_t) -1);
TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch); TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0); TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0); TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
free_fill_heap (heap_filler); free_fill_heap (heap_filler);
} }

View File

@ -48,9 +48,9 @@ struct str_array
({ \ ({ \
TEST_VERIFY_EXIT (!dynarray_##type##_has_failed (dyn)); \ TEST_VERIFY_EXIT (!dynarray_##type##_has_failed (dyn)); \
TEST_VERIFY_EXIT (dynarray_##type##_size (dyn) == 0); \ TEST_VERIFY_EXIT (dynarray_##type##_size (dyn) == 0); \
TEST_VERIFY_EXIT ((dyn)->dynarray_header.array \ TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.array \
== (dyn)->scratch); \ == (dyn)->scratch); \
TEST_VERIFY_EXIT ((dyn)->dynarray_header.allocated > 0); \ TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.allocated > 0); \
(void) 0; \ (void) 0; \
}) })

View File

@ -110,10 +110,10 @@ test_int (void)
TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == i + 1); TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == i + 1);
TEST_VERIFY_EXIT (dynarray_int_size (&dyn) TEST_VERIFY_EXIT (dynarray_int_size (&dyn)
<= dyn.dynarray_header.allocated); <= dyn.u.dynarray_header.allocated);
} }
TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count); TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count);
TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated); TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
if (count > 0) if (count > 0)
{ {
TEST_VERIFY (dynarray_int_begin (&dyn) TEST_VERIFY (dynarray_int_begin (&dyn)
@ -122,7 +122,7 @@ test_int (void)
== dynarray_int_at (&dyn, count - 1) + 1); == dynarray_int_at (&dyn, count - 1) + 1);
} }
unsigned final_count; unsigned final_count;
bool heap_array = dyn.dynarray_header.array != dyn.scratch; bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
if (do_remove_last) if (do_remove_last)
{ {
dynarray_int_remove_last (&dyn); dynarray_int_remove_last (&dyn);
@ -146,10 +146,11 @@ test_int (void)
final_count = 0; final_count = 0;
} }
TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch) TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
== heap_array); == heap_array);
TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count); TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count);
TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count); TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
>= final_count);
if (!do_clear) if (!do_clear)
for (unsigned int i = 0; i < final_count; ++i) for (unsigned int i = 0; i < final_count; ++i)
TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i); TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i);
@ -238,10 +239,10 @@ test_str (void)
TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == i + 1); TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == i + 1);
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) TEST_VERIFY_EXIT (dynarray_str_size (&dyn)
<= dyn.dynarray_header.allocated); <= dyn.u.dynarray_header.allocated);
} }
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count); TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count);
TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated); TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
if (count > 0) if (count > 0)
{ {
TEST_VERIFY (dynarray_str_begin (&dyn) TEST_VERIFY (dynarray_str_begin (&dyn)
@ -250,7 +251,7 @@ test_str (void)
== dynarray_str_at (&dyn, count - 1) + 1); == dynarray_str_at (&dyn, count - 1) + 1);
} }
unsigned final_count; unsigned final_count;
bool heap_array = dyn.dynarray_header.array != dyn.scratch; bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
if (do_remove_last) if (do_remove_last)
{ {
dynarray_str_remove_last (&dyn); dynarray_str_remove_last (&dyn);
@ -274,10 +275,11 @@ test_str (void)
final_count = 0; final_count = 0;
} }
TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn)); TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch) TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
== heap_array); == heap_array);
TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count); TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count);
TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count); TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
>= final_count);
if (!do_clear) if (!do_clear)
for (unsigned int i = 0; i < count - do_remove_last; ++i) for (unsigned int i = 0; i < count - do_remove_last; ++i)
{ {