diff options
Diffstat (limited to 'gl/realloc.c')
| -rw-r--r-- | gl/realloc.c | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/gl/realloc.c b/gl/realloc.c index 05731396..04a28561 100644 --- a/gl/realloc.c +++ b/gl/realloc.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* realloc() function that is glibc compatible. | 1 | /* realloc() function that is glibc compatible. |
| 2 | 2 | ||
| 3 | Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2024 Free Software | 3 | Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2025 Free Software |
| 4 | Foundation, Inc. | 4 | Foundation, Inc. |
| 5 | 5 | ||
| 6 | This file is free software: you can redistribute it and/or modify | 6 | This file is free software: you can redistribute it and/or modify |
| @@ -18,17 +18,21 @@ | |||
| 18 | 18 | ||
| 19 | /* written by Jim Meyering and Bruno Haible */ | 19 | /* written by Jim Meyering and Bruno Haible */ |
| 20 | 20 | ||
| 21 | /* Ensure that we call the system's realloc() below. */ | ||
| 22 | #define _GL_USE_STDLIB_ALLOC 1 | ||
| 21 | #include <config.h> | 23 | #include <config.h> |
| 22 | 24 | ||
| 25 | #define _GL_REALLOC_INLINE _GL_EXTERN_INLINE | ||
| 23 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 24 | 27 | ||
| 25 | #include <errno.h> | 28 | #include <errno.h> |
| 29 | #include <stdckdint.h> | ||
| 26 | 30 | ||
| 27 | #include "xalloc-oversized.h" | 31 | #ifdef __CHERI_PURE_CAPABILITY__ |
| 32 | # include <cheri.h> | ||
| 33 | #endif | ||
| 28 | 34 | ||
| 29 | /* Call the system's realloc below. This file does not define | 35 | #ifndef _GL_INLINE_RPL_REALLOC |
| 30 | _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present. */ | ||
| 31 | #undef realloc | ||
| 32 | 36 | ||
| 33 | /* Change the size of an allocated block of memory P to N bytes, | 37 | /* Change the size of an allocated block of memory P to N bytes, |
| 34 | with error checking. If P is NULL, use malloc. Otherwise if N is zero, | 38 | with error checking. If P is NULL, use malloc. Otherwise if N is zero, |
| @@ -37,27 +41,70 @@ | |||
| 37 | void * | 41 | void * |
| 38 | rpl_realloc (void *p, size_t n) | 42 | rpl_realloc (void *p, size_t n) |
| 39 | { | 43 | { |
| 40 | if (p == NULL) | 44 | size_t n1 = n; |
| 41 | return malloc (n); | ||
| 42 | 45 | ||
| 43 | if (n == 0) | 46 | if (n == 0) |
| 44 | { | 47 | { |
| 45 | free (p); | 48 | # if NEED_SANITIZED_REALLOC |
| 46 | return NULL; | 49 | /* When P is non-null, ISO C23 ยง7.24.3.7.(3) says realloc (P, 0) has |
| 50 | undefined behavior even though C17 and earlier partially defined | ||
| 51 | the behavior. Let the programmer know. | ||
| 52 | When the undefined-behaviour sanitizers report this case, i.e. when | ||
| 53 | <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117233> and | ||
| 54 | <https://github.com/llvm/llvm-project/issues/113065> | ||
| 55 | have been closed and new releases of GCC and clang have been made, | ||
| 56 | we can revisit this code. */ | ||
| 57 | if (p != NULL) | ||
| 58 | abort (); | ||
| 59 | # endif | ||
| 60 | |||
| 61 | /* realloc (NULL, 0) acts like glibc malloc (0), i.e., like malloc (1) | ||
| 62 | except the caller cannot dereference any non-null return. | ||
| 63 | |||
| 64 | realloc (P, 0) with non-null P is a messier situation. | ||
| 65 | As mentioned above, C23 says behavior is undefined. | ||
| 66 | POSIX.1-2024 extends C17 to say realloc (P, 0) | ||
| 67 | either fails by setting errno and returning a null pointer, | ||
| 68 | or succeeds by freeing P and then either: | ||
| 69 | (a) setting errno=EINVAL and returning a null pointer; or | ||
| 70 | (b) acting like a successful malloc (0). | ||
| 71 | glibc 1 through 2.1 realloc acted like (b), | ||
| 72 | which conforms to C17, to C23 and to POSIX.1-2024. | ||
| 73 | glibc 2.1.1+ realloc acts like (a) except it does not set errno; | ||
| 74 | this conforms to C17 and to C23 but not to POSIX.1-2024. | ||
| 75 | Quite possibly future versions of POSIX will change, | ||
| 76 | due either to C23 or to (a)'s semantics being messy. | ||
| 77 | Act like (b), as that's easy, matches GNU, BSD and V7 malloc, | ||
| 78 | matches BSD and V7 realloc, and requires no extra code at | ||
| 79 | caller sites. */ | ||
| 80 | |||
| 81 | # if !HAVE_REALLOC_0_NONNULL | ||
| 82 | n1 = 1; | ||
| 83 | # endif | ||
| 47 | } | 84 | } |
| 48 | 85 | ||
| 49 | if (xalloc_oversized (n, 1)) | 86 | # if !HAVE_MALLOC_PTRDIFF |
| 87 | ptrdiff_t signed_n; | ||
| 88 | if (ckd_add (&signed_n, n, 0)) | ||
| 50 | { | 89 | { |
| 51 | errno = ENOMEM; | 90 | errno = ENOMEM; |
| 52 | return NULL; | 91 | return NULL; |
| 53 | } | 92 | } |
| 93 | # endif | ||
| 54 | 94 | ||
| 55 | void *result = realloc (p, n); | 95 | void *result = realloc (p, n1); |
| 56 | 96 | ||
| 57 | #if !HAVE_MALLOC_POSIX | 97 | # if !HAVE_REALLOC_POSIX |
| 58 | if (result == NULL) | 98 | if (result == NULL) |
| 59 | errno = ENOMEM; | 99 | errno = ENOMEM; |
| 60 | #endif | 100 | # endif |
| 101 | |||
| 102 | # ifdef __CHERI_PURE_CAPABILITY__ | ||
| 103 | if (result != NULL) | ||
| 104 | result = cheri_bounds_set (result, n); | ||
| 105 | # endif | ||
| 61 | 106 | ||
| 62 | return result; | 107 | return result; |
| 63 | } | 108 | } |
| 109 | |||
| 110 | #endif | ||
