From ce2379cc29a1923a53fb588e60494dbbc07cb47c Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 29 Jul 2026 12:57:43 +0200 Subject: [PATCH 1/7] lib/cast.h: rvalue(): Add macro for performing lvalue conversion This macro takes an lvalue, and performs lvalue conversion, resulting in an rvalue. Signed-off-by: Alejandro Colomar --- lib/cast.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cast.h b/lib/cast.h index e8e42e1a0b..d87f8bf36d 100644 --- a/lib/cast.h +++ b/lib/cast.h @@ -11,5 +11,7 @@ #define const_cast(T, p) _Generic(p, const T: (T) (p)) +#define rvalue(lv) ({(lv);}) + #endif // include guard From 711e15b8c147566b5f3904d0f1c9786a54117f27 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 11 Jan 2026 00:15:25 +0100 Subject: [PATCH 2/7] lib/: Use rvalue() instead of its pattern This helps document that we're forcing lvalue conversion on purpose, for safety reasons. Signed-off-by: Alejandro Colomar --- lib/alloc/calloc.h | 6 ++---- lib/alloc/malloc.h | 6 ++---- lib/alloc/realloc.h | 9 +++++---- lib/alloc/reallocf.h | 9 +++++---- lib/search/l/lfind.h | 11 ++++++----- lib/sizeof.h | 4 +++- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/alloc/calloc.h b/lib/alloc/calloc.h index db10a685bb..9b32c5ef61 100644 --- a/lib/alloc/calloc.h +++ b/lib/alloc/calloc.h @@ -10,16 +10,14 @@ #include +#include "cast.h" #include "exit_if_null.h" #include "sizeof.h" // calloc_T - calloc type-safe #define calloc_T(n, T) calloc_T_(n, typeas(T)) -#define calloc_T_(n, T) \ -({ \ - (T *){calloc(n, sizeof(T))}; \ -}) +#define calloc_T_(n, T) rvalue((T *){calloc(n, sizeof(T))}) // xcalloc_T - exit-on-error calloc type-safe diff --git a/lib/alloc/malloc.h b/lib/alloc/malloc.h index 1e3a69291a..53602ea732 100644 --- a/lib/alloc/malloc.h +++ b/lib/alloc/malloc.h @@ -11,16 +11,14 @@ #include #include "attr.h" +#include "cast.h" #include "exit_if_null.h" #include "sizeof.h" // malloc_T - malloc type-safe #define malloc_T(n, T) malloc_T_(n, typeas(T)) -#define malloc_T_(n, T) \ -({ \ - (T *){mallocarray(n, sizeof(T))}; \ -}) +#define malloc_T_(n, T) rvalue((T *){mallocarray(n, sizeof(T))}) // xmalloc_T - exit-on-error malloc type-safe diff --git a/lib/alloc/realloc.h b/lib/alloc/realloc.h index ac9f046ec6..448729b382 100644 --- a/lib/alloc/realloc.h +++ b/lib/alloc/realloc.h @@ -10,6 +10,7 @@ #include +#include "cast.h" #include "exit_if_null.h" #include "sizeof.h" @@ -17,10 +18,10 @@ // realloc_T - realloc type-safe #define realloc_T(p, n, T) realloc_T_(p, n, typeas(T)) #define realloc_T_(p, n, T) \ -({ \ - _Generic(p, T *: (void)0); \ - (T *){reallocarray_(p, n, sizeof(T))}; \ -}) +( \ + _Generic(p, T *: (void)0), \ + rvalue((T *){reallocarray_(p, n, sizeof(T))}) \ +) #define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1) diff --git a/lib/alloc/reallocf.h b/lib/alloc/reallocf.h index c3522829d6..0d9a484f26 100644 --- a/lib/alloc/reallocf.h +++ b/lib/alloc/reallocf.h @@ -12,16 +12,17 @@ #include #include "attr.h" +#include "cast.h" #include "sizeof.h" // reallocf_T - realloc free-on-error type-safe #define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T)) #define reallocf_T_(p, n, T) \ -({ \ - _Generic(p, T *: (void)0); \ - (T *){reallocarrayf_(p, n, sizeof(T))}; \ -}) +( \ + _Generic(p, T *: (void)0), \ + rvalue((T *){reallocarrayf_(p, n, sizeof(T))}) \ +) #define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1) diff --git a/lib/search/l/lfind.h b/lib/search/l/lfind.h index 7bbd16e0e3..73b53ec4aa 100644 --- a/lib/search/l/lfind.h +++ b/lib/search/l/lfind.h @@ -11,6 +11,7 @@ #include #include +#include "cast.h" #include "search/cmp/cmp.h" #include "sizeof.h" @@ -18,11 +19,11 @@ // lfind_T - linear find type-safe #define lfind_T(T, ...) lfind_T_(typeas(T), __VA_ARGS__) #define lfind_T_(T, k, a, n, cmp) \ -({ \ - _Generic(k, T *: (void)0, const T *: (void)0); \ - _Generic(a, T *: (void)0, const T *: (void)0); \ - (T *){lfind_(k, a, n, sizeof(T), cmp)}; \ -}) +( \ + _Generic(k, T *: (void)0, const T *: (void)0), \ + _Generic(a, T *: (void)0, const T *: (void)0), \ + rvalue((T *){lfind_(k, a, n, sizeof(T), cmp)}) \ +) #define LFIND(T, ...) lfind_T(T, __VA_ARGS__, CMP(T)) diff --git a/lib/sizeof.h b/lib/sizeof.h index 1fc38873dd..e9aa343a0b 100644 --- a/lib/sizeof.h +++ b/lib/sizeof.h @@ -14,10 +14,12 @@ #endif #include +#include "cast.h" + #define typeas(T) typeof((T){0}) -#define ssizeof(x) ({(ssize_t){sizeof(x)};}) +#define ssizeof(x) rvalue((ssize_t){sizeof(x)}) #define memberof(T, member) ((T){}.member) #define WIDTHOF(x) (sizeof(x) * CHAR_BIT) From 86b395f375f13b4fee080d8c4825b55125e11fb1 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 11 Jan 2026 00:15:25 +0100 Subject: [PATCH 3/7] lib/cast.h: rvalue(): Use the comma operator to perform lvalue conversion Statement expressions are non-standard, and quite complex within the compiler, so it would be interesting to use simpler compiler features to achieve the same. The comma operator also performs lvalue conversion, and we can use a dummy (void)0 expression to introduce it. This is significantly simpler, and is more portable than the statement expression: it is valid all the way back to C99 (the comma operator and the (void)0 expression are portable to C89, but the compound literal is from C99). By using a simpler feature, we have a smaller risk of running into a compiler bug. Suggested-by: Martin Uecker Cc: Christopher Bazley Cc: Kees Cook Cc: Richard Russon Signed-off-by: Alejandro Colomar --- lib/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cast.h b/lib/cast.h index d87f8bf36d..e96c4a4159 100644 --- a/lib/cast.h +++ b/lib/cast.h @@ -11,7 +11,7 @@ #define const_cast(T, p) _Generic(p, const T: (T) (p)) -#define rvalue(lv) ({(lv);}) +#define rvalue(lv) ((void)0, (lv)) #endif // include guard From 563528cdd04f3a476e1523e602a258888cc9668a Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 31 Jul 2026 16:05:42 +0200 Subject: [PATCH 4/7] lib/alloc/: mallocarray(): Define as a macro It's much simpler. Signed-off-by: Alejandro Colomar --- lib/alloc/malloc.c | 11 +---------- lib/alloc/malloc.h | 14 ++------------ 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/lib/alloc/malloc.c b/lib/alloc/malloc.c index 97557a7fc4..31ed42814f 100644 --- a/lib/alloc/malloc.c +++ b/lib/alloc/malloc.c @@ -1,16 +1,7 @@ -// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh -// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz -// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko -// SPDX-FileCopyrightText: 2008 , Nicolas François -// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar +// SPDX-FileCopyrightText: 2023-2026, Alejandro Colomar // SPDX-License-Identifier: BSD-3-Clause #include "config.h" #include "alloc/malloc.h" - -#include - - -extern inline void *mallocarray(size_t nmemb, size_t size); diff --git a/lib/alloc/malloc.h b/lib/alloc/malloc.h index 53602ea732..7b270918fa 100644 --- a/lib/alloc/malloc.h +++ b/lib/alloc/malloc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar +// SPDX-FileCopyrightText: 2023-2026, Alejandro Colomar // SPDX-License-Identifier: BSD-3-Clause @@ -10,7 +10,6 @@ #include -#include "attr.h" #include "cast.h" #include "exit_if_null.h" #include "sizeof.h" @@ -26,16 +25,7 @@ // mallocarray - malloc array -ATTR_ALLOC_SIZE(1, 2) -ATTR_MALLOC(free) -inline void *mallocarray(size_t nmemb, size_t size); - - -inline void * -mallocarray(size_t nmemb, size_t size) -{ - return reallocarray(NULL, nmemb, size); -} +#define mallocarray(...) reallocarray(NULL, __VA_ARGS__) #endif // include guard From 855ad495845edf394f6628b4bec05f73d054aea9 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 8 Aug 2026 13:41:04 +0200 Subject: [PATCH 5/7] lib/alloc/, lib/: Compact files under lib/alloc/ Signed-off-by: Alejandro Colomar --- lib/Makefile.am | 10 +--- lib/addgrps.c | 2 +- lib/agetpass.c | 2 +- lib/alloc/{malloc.c => alloc.c} | 7 ++- lib/alloc/alloc.h | 76 ++++++++++++++++++++++++++++ lib/alloc/calloc.c | 11 ---- lib/alloc/calloc.h | 27 ---------- lib/alloc/malloc.h | 31 ------------ lib/alloc/realloc.c | 11 ---- lib/alloc/realloc.h | 33 ------------ lib/alloc/reallocf.c | 16 ------ lib/alloc/reallocf.h | 49 ------------------ lib/commonio.c | 2 +- lib/copydir.c | 2 +- lib/env.c | 3 +- lib/find_new_gid.c | 2 +- lib/find_new_uid.c | 2 +- lib/fs/readlink/areadlink.h | 2 +- lib/groupio.c | 3 +- lib/groupmem.c | 3 +- lib/idmapping.c | 3 +- lib/list.c | 2 +- lib/nss.c | 2 +- lib/pam_pass_non_interactive.c | 2 +- lib/pwmem.c | 2 +- lib/sgroupio.c | 3 +- lib/shadow/group/sgetgrent.c | 2 +- lib/shadow/grp/agetgroups.h | 2 +- lib/shadow/gshadow/fgetsgent.c | 3 +- lib/shadow/gshadow/putsgent.c | 2 +- lib/shadowmem.c | 2 +- lib/sssd.c | 2 +- lib/string/strdup/memdup.h | 2 +- lib/string/strtok/astrsep2ls.h | 2 +- lib/subordinateio.c | 3 +- lib/utmp.c | 3 +- lib/xgetXXbyYY.c | 3 +- src/gpasswd.c | 2 +- src/groupmod.c | 2 +- src/login.c | 2 +- src/newgrp.c | 3 +- src/newusers.c | 2 +- src/su.c | 2 +- src/useradd.c | 2 +- src/usermod.c | 2 +- tests/libsubid/04_nss/libsubid_zzz.c | 4 +- tests/unit/test_chkname.c | 2 +- tests/unit/test_exit_if_null.c | 2 +- 48 files changed, 124 insertions(+), 235 deletions(-) rename lib/alloc/{malloc.c => alloc.c} (53%) create mode 100644 lib/alloc/alloc.h delete mode 100644 lib/alloc/calloc.c delete mode 100644 lib/alloc/calloc.h delete mode 100644 lib/alloc/malloc.h delete mode 100644 lib/alloc/realloc.c delete mode 100644 lib/alloc/realloc.h delete mode 100644 lib/alloc/reallocf.c delete mode 100644 lib/alloc/reallocf.h diff --git a/lib/Makefile.am b/lib/Makefile.am index d709345986..7ce135e35b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,14 +29,8 @@ libshadow_la_SOURCES = \ age.c \ agetpass.c \ agetpass.h \ - alloc/calloc.c \ - alloc/calloc.h \ - alloc/malloc.c \ - alloc/malloc.h \ - alloc/realloc.c \ - alloc/realloc.h \ - alloc/reallocf.c \ - alloc/reallocf.h \ + alloc/alloc.c \ + alloc/alloc.h \ atoi/a2i.c \ atoi/a2i.h \ atoi/getnum.c \ diff --git a/lib/addgrps.c b/lib/addgrps.c index 7413ef9116..67a0fbc3b4 100644 --- a/lib/addgrps.c +++ b/lib/addgrps.c @@ -19,7 +19,7 @@ #include #include -#include "alloc/reallocf.h" +#include "alloc/alloc.h" #include "io/fprintf.h" #include "search/l/lsearch.h" #include "shadow/grp/agetgroups.h" diff --git a/lib/agetpass.c b/lib/agetpass.c index a0d5714959..1d2f70b3b7 100644 --- a/lib/agetpass.c +++ b/lib/agetpass.c @@ -16,7 +16,7 @@ #ident "$Id$" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #if WITH_LIBBSD == 0 #include "freezero.h" diff --git a/lib/alloc/malloc.c b/lib/alloc/alloc.c similarity index 53% rename from lib/alloc/malloc.c rename to lib/alloc/alloc.c index 31ed42814f..dd8d213592 100644 --- a/lib/alloc/malloc.c +++ b/lib/alloc/alloc.c @@ -4,4 +4,9 @@ #include "config.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" + +#include + + +extern inline void *reallocarrayf(void *p, size_t nmemb, size_t size); diff --git a/lib/alloc/alloc.h b/lib/alloc/alloc.h new file mode 100644 index 0000000000..793158ca43 --- /dev/null +++ b/lib/alloc/alloc.h @@ -0,0 +1,76 @@ +// SPDX-FileCopyrightText: 2023-2026, Alejandro Colomar +// SPDX-License-Identifier: BSD-3-Clause + + +#ifndef SHADOW_INCLUDE_LIB_ALLOC_ALLOC_H_ +#define SHADOW_INCLUDE_LIB_ALLOC_ALLOC_H_ + + +#include "config.h" + +#include +#include + +#include "cast.h" +#include "exit_if_null.h" +#include "sizeof.h" + + +// malloc_T - malloc type-safe +#define malloc_T(n, T) malloc_T_(n, typeas(T)) +#define malloc_T_(n, T) rvalue((T *){mallocarray(n, sizeof(T))}) +// calloc_T - calloc type-safe +#define calloc_T(n, T) calloc_T_(n, typeas(T)) +#define calloc_T_(n, T) rvalue((T *){calloc(n, sizeof(T))}) +// realloc_T - realloc type-safe +#define realloc_T(p, n, T) realloc_T_(p, n, typeas(T)) +#define realloc_T_(p, n, T) \ +( \ + _Generic(p, T *: (void)0), \ + rvalue((T *){reallocarray_(p, n, sizeof(T))}) \ +) +// reallocf_T - realloc free-on-error type-safe +#define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T)) +#define reallocf_T_(p, n, T) \ +( \ + _Generic(p, T *: (void)0), \ + rvalue((T *){reallocarrayf_(p, n, sizeof(T))}) \ +) + + +// xmalloc_T - exit-on-error malloc type-safe +#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T)) +// xcalloc_T - exit-on-error calloc type-safe +#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T)) +// xrealloc_T - exit-on-error realloc type-safe +#define xrealloc_T(p, n, T) exit_if_null(realloc_T(p, n, T)) + + +// mallocarray - malloc array +#define mallocarray(...) reallocarray(NULL, __VA_ARGS__) + + +#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1) +#define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1) + + +// reallocarrayf - realloc array free-on-error +ATTR_ALLOC_SIZE(2, 3) +ATTR_MALLOC(free) +inline void *reallocarrayf(void *p, size_t nmemb, size_t size); + + +inline void * +reallocarrayf(void *p, size_t nmemb, size_t size) +{ + void *q; + + q = reallocarray(p, nmemb ?: 1, size ?: 1); + + if (q == NULL) + free(p); + return q; +} + + +#endif // include guard diff --git a/lib/alloc/calloc.c b/lib/alloc/calloc.c deleted file mode 100644 index 55807f94c7..0000000000 --- a/lib/alloc/calloc.c +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh -// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz -// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko -// SPDX-FileCopyrightText: 2008 , Nicolas François -// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "alloc/calloc.h" diff --git a/lib/alloc/calloc.h b/lib/alloc/calloc.h deleted file mode 100644 index 9b32c5ef61..0000000000 --- a/lib/alloc/calloc.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_ -#define SHADOW_INCLUDE_LIB_ALLOC_CALLOC_H_ - - -#include "config.h" - -#include - -#include "cast.h" -#include "exit_if_null.h" -#include "sizeof.h" - - -// calloc_T - calloc type-safe -#define calloc_T(n, T) calloc_T_(n, typeas(T)) -#define calloc_T_(n, T) rvalue((T *){calloc(n, sizeof(T))}) - - -// xcalloc_T - exit-on-error calloc type-safe -#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T)) - - -#endif // include guard diff --git a/lib/alloc/malloc.h b/lib/alloc/malloc.h deleted file mode 100644 index 7b270918fa..0000000000 --- a/lib/alloc/malloc.h +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2026, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_ -#define SHADOW_INCLUDE_LIB_ALLOC_MALLOC_H_ - - -#include "config.h" - -#include - -#include "cast.h" -#include "exit_if_null.h" -#include "sizeof.h" - - -// malloc_T - malloc type-safe -#define malloc_T(n, T) malloc_T_(n, typeas(T)) -#define malloc_T_(n, T) rvalue((T *){mallocarray(n, sizeof(T))}) - - -// xmalloc_T - exit-on-error malloc type-safe -#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T)) - - -// mallocarray - malloc array -#define mallocarray(...) reallocarray(NULL, __VA_ARGS__) - - -#endif // include guard diff --git a/lib/alloc/realloc.c b/lib/alloc/realloc.c deleted file mode 100644 index ad390e70aa..0000000000 --- a/lib/alloc/realloc.c +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh -// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz -// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko -// SPDX-FileCopyrightText: 2008 , Nicolas François -// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "alloc/realloc.h" diff --git a/lib/alloc/realloc.h b/lib/alloc/realloc.h deleted file mode 100644 index 448729b382..0000000000 --- a/lib/alloc/realloc.h +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_ -#define SHADOW_INCLUDE_LIB_ALLOC_REALLOC_H_ - - -#include "config.h" - -#include - -#include "cast.h" -#include "exit_if_null.h" -#include "sizeof.h" - - -// realloc_T - realloc type-safe -#define realloc_T(p, n, T) realloc_T_(p, n, typeas(T)) -#define realloc_T_(p, n, T) \ -( \ - _Generic(p, T *: (void)0), \ - rvalue((T *){reallocarray_(p, n, sizeof(T))}) \ -) - -#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1) - - -// xrealloc_T - exit-on-error realloc type-safe -#define xrealloc_T(p, n, T) exit_if_null(realloc_T(p, n, T)) - - -#endif // include guard diff --git a/lib/alloc/reallocf.c b/lib/alloc/reallocf.c deleted file mode 100644 index 66ae68cd8e..0000000000 --- a/lib/alloc/reallocf.c +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-FileCopyrightText: 1990-1994, Julianne Frances Haugh -// SPDX-FileCopyrightText: 1996-1998, Marek Michałkiewicz -// SPDX-FileCopyrightText: 2003-2006, Tomasz Kłoczko -// SPDX-FileCopyrightText: 2008 , Nicolas François -// SPDX-FileCopyrightText: 2023-2024, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#include "config.h" - -#include "alloc/reallocf.h" - -#include - - -extern inline void *reallocarrayf(void *p, size_t nmemb, size_t size); diff --git a/lib/alloc/reallocf.h b/lib/alloc/reallocf.h deleted file mode 100644 index 0d9a484f26..0000000000 --- a/lib/alloc/reallocf.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: 2023-2025, Alejandro Colomar -// SPDX-License-Identifier: BSD-3-Clause - - -#ifndef SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_ -#define SHADOW_INCLUDE_LIB_ALLOC_REALLOCF_H_ - - -#include "config.h" - -#include -#include - -#include "attr.h" -#include "cast.h" -#include "sizeof.h" - - -// reallocf_T - realloc free-on-error type-safe -#define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T)) -#define reallocf_T_(p, n, T) \ -( \ - _Generic(p, T *: (void)0), \ - rvalue((T *){reallocarrayf_(p, n, sizeof(T))}) \ -) - -#define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1) - - -// reallocarrayf - realloc array free-on-error -ATTR_ALLOC_SIZE(2, 3) -ATTR_MALLOC(free) -inline void *reallocarrayf(void *p, size_t nmemb, size_t size); - - -inline void * -reallocarrayf(void *p, size_t nmemb, size_t size) -{ - void *q; - - q = reallocarray(p, nmemb ?: 1, size ?: 1); - - if (q == NULL) - free(p); - return q; -} - - -#endif // include guard diff --git a/lib/commonio.c b/lib/commonio.c index da530ef222..500ae011c2 100644 --- a/lib/commonio.c +++ b/lib/commonio.c @@ -20,7 +20,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/getnum.h" #include "commonio.h" #include "defines.h" diff --git a/lib/copydir.c b/lib/copydir.c index 42e9e7332d..9ca20f0499 100644 --- a/lib/copydir.c +++ b/lib/copydir.c @@ -16,7 +16,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "fs/readlink/areadlink.h" #include "io/fprintf.h" diff --git a/lib/env.c b/lib/env.c index 37edc05907..11d21b44d3 100644 --- a/lib/env.c +++ b/lib/env.c @@ -13,8 +13,7 @@ #include #include -#include "alloc/malloc.h" -#include "alloc/realloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "defines.h" #include "shadowlog.h" diff --git a/lib/find_new_gid.c b/lib/find_new_gid.c index e25f191b9f..35307cba0f 100644 --- a/lib/find_new_gid.c +++ b/lib/find_new_gid.c @@ -12,7 +12,7 @@ #include #include -#include "alloc/calloc.h" +#include "alloc/alloc.h" #include "groupio.h" #include "getdef.h" #include "io/fprintf.h" diff --git a/lib/find_new_uid.c b/lib/find_new_uid.c index 99e98c4920..580c29a07e 100644 --- a/lib/find_new_uid.c +++ b/lib/find_new_uid.c @@ -12,7 +12,7 @@ #include #include -#include "alloc/calloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "pwio.h" #include "getdef.h" diff --git a/lib/fs/readlink/areadlink.h b/lib/fs/readlink/areadlink.h index 2a35be75ed..9da4cf18d4 100644 --- a/lib/fs/readlink/areadlink.h +++ b/lib/fs/readlink/areadlink.h @@ -14,7 +14,7 @@ #include #include "defines.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "fs/readlink/readlinknul.h" diff --git a/lib/groupio.c b/lib/groupio.c index 119afa33df..b94525e827 100644 --- a/lib/groupio.c +++ b/lib/groupio.c @@ -12,8 +12,7 @@ #include -#include "alloc/calloc.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "commonio.h" #include "defines.h" #include "fields.h" diff --git a/lib/groupmem.c b/lib/groupmem.c index 1ebe2f9ba0..0ef6a09c9a 100644 --- a/lib/groupmem.c +++ b/lib/groupmem.c @@ -12,8 +12,7 @@ #ident "$Id$" -#include "alloc/calloc.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "defines.h" #include "groupio.h" diff --git a/lib/idmapping.c b/lib/idmapping.c index ad399b38f4..4ba086ad9f 100644 --- a/lib/idmapping.c +++ b/lib/idmapping.c @@ -19,8 +19,7 @@ # include #endif -#include "alloc/calloc.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/a2i.h" #include "attr.h" #include "idmapping.h" diff --git a/lib/list.c b/lib/list.c index bafcd14618..791157782a 100644 --- a/lib/list.c +++ b/lib/list.c @@ -8,7 +8,7 @@ #include "config.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "defines.h" #include "string/strchr/strchrcnt.h" diff --git a/lib/nss.c b/lib/nss.c index 583f0b65f3..777b176b15 100644 --- a/lib/nss.c +++ b/lib/nss.c @@ -9,7 +9,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "io/fprintf.h" #include "prototypes.h" #include "../libsubid/subid.h" diff --git a/lib/pam_pass_non_interactive.c b/lib/pam_pass_non_interactive.c index 6a8dcd78cf..718503bd9f 100644 --- a/lib/pam_pass_non_interactive.c +++ b/lib/pam_pass_non_interactive.c @@ -14,7 +14,7 @@ #include -#include "alloc/calloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "prototypes.h" #include "shadowlog.h" diff --git a/lib/pwmem.c b/lib/pwmem.c index b86be4b3a1..cb17700767 100644 --- a/lib/pwmem.c +++ b/lib/pwmem.c @@ -14,7 +14,7 @@ #include -#include "alloc/calloc.h" +#include "alloc/alloc.h" #include "defines.h" #include "prototypes.h" #include "pwio.h" diff --git a/lib/sgroupio.c b/lib/sgroupio.c index ad3adc3463..dd0345f7a8 100644 --- a/lib/sgroupio.c +++ b/lib/sgroupio.c @@ -14,8 +14,7 @@ #include -#include "alloc/calloc.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "defines.h" #include "commonio.h" diff --git a/lib/shadow/group/sgetgrent.c b/lib/shadow/group/sgetgrent.c index 2a13091ef0..c1e33bb431 100644 --- a/lib/shadow/group/sgetgrent.c +++ b/lib/shadow/group/sgetgrent.c @@ -16,7 +16,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/getnum.h" #include "defines.h" #include "prototypes.h" diff --git a/lib/shadow/grp/agetgroups.h b/lib/shadow/grp/agetgroups.h index 8c1c2f95ee..f6be3eb507 100644 --- a/lib/shadow/grp/agetgroups.h +++ b/lib/shadow/grp/agetgroups.h @@ -13,7 +13,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" diff --git a/lib/shadow/gshadow/fgetsgent.c b/lib/shadow/gshadow/fgetsgent.c index 0af9c6015f..cd15fa1ec2 100644 --- a/lib/shadow/gshadow/fgetsgent.c +++ b/lib/shadow/gshadow/fgetsgent.c @@ -14,8 +14,7 @@ #include #include -#include "alloc/malloc.h" -#include "alloc/realloc.h" +#include "alloc/alloc.h" #include "defines.h" #include "prototypes.h" #include "shadow/gshadow/sgetsgent.h" diff --git a/lib/shadow/gshadow/putsgent.c b/lib/shadow/gshadow/putsgent.c index 7a7b98727f..e4a55ce2f6 100644 --- a/lib/shadow/gshadow/putsgent.c +++ b/lib/shadow/gshadow/putsgent.c @@ -15,7 +15,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "shadow/gshadow/sgrp.h" diff --git a/lib/shadowmem.c b/lib/shadowmem.c index 751a511b70..93f4696dba 100644 --- a/lib/shadowmem.c +++ b/lib/shadowmem.c @@ -17,7 +17,7 @@ #include #include -#include "alloc/calloc.h" +#include "alloc/alloc.h" #include "shadowio.h" #include "string/memset/memzero.h" diff --git a/lib/sssd.c b/lib/sssd.c index cc5d4a464d..2d1a2dd706 100644 --- a/lib/sssd.c +++ b/lib/sssd.c @@ -10,7 +10,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "exitcodes.h" #include "defines.h" #include "prototypes.h" diff --git a/lib/string/strdup/memdup.h b/lib/string/strdup/memdup.h index cbae5158f8..d8596e24ab 100644 --- a/lib/string/strdup/memdup.h +++ b/lib/string/strdup/memdup.h @@ -10,7 +10,7 @@ #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" // memdup_T - memory duplicate type-safe diff --git a/lib/string/strtok/astrsep2ls.h b/lib/string/strtok/astrsep2ls.h index aa9283a119..5f8c5c3aac 100644 --- a/lib/string/strtok/astrsep2ls.h +++ b/lib/string/strtok/astrsep2ls.h @@ -10,7 +10,7 @@ #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "exit_if_null.h" #include "string/strchr/strchrscnt.h" diff --git a/lib/subordinateio.c b/lib/subordinateio.c index 8542d79327..141791fab9 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -21,8 +21,7 @@ #include #include -#include "alloc/malloc.h" -#include "alloc/reallocf.h" +#include "alloc/alloc.h" #include "atoi/a2i.h" #include "atoi/getnum.h" #include "shadow/passwd/getpw.h" diff --git a/lib/utmp.c b/lib/utmp.c index 62002768e6..49efb6e96e 100644 --- a/lib/utmp.c +++ b/lib/utmp.c @@ -26,8 +26,7 @@ #include #include -#include "alloc/calloc.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "io/syslog.h" #include "sizeof.h" diff --git a/lib/xgetXXbyYY.c b/lib/xgetXXbyYY.c index 5890212072..7554f5ffb1 100644 --- a/lib/xgetXXbyYY.c +++ b/lib/xgetXXbyYY.c @@ -32,8 +32,7 @@ #include #include -#include "alloc/malloc.h" -#include "alloc/realloc.h" +#include "alloc/alloc.h" #include "prototypes.h" #include "shadowlog.h" diff --git a/src/gpasswd.c b/src/gpasswd.c index 3e68632a3f..860c301a3d 100644 --- a/src/gpasswd.c +++ b/src/gpasswd.c @@ -21,7 +21,7 @@ #include #include "agetpass.h" -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "defines.h" /*@-exitarg@*/ diff --git a/src/groupmod.c b/src/groupmod.c index cac27214c4..c01dabe52f 100644 --- a/src/groupmod.c +++ b/src/groupmod.c @@ -21,7 +21,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/getnum.h" #include "chkname.h" #include "defines.h" diff --git a/src/login.c b/src/login.c index 951125c6f1..cf9d2be70f 100644 --- a/src/login.c +++ b/src/login.c @@ -26,7 +26,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "chkname.h" #include "defines.h" diff --git a/src/newgrp.c b/src/newgrp.c index 69ee7c5611..1204b18ff9 100644 --- a/src/newgrp.c +++ b/src/newgrp.c @@ -17,8 +17,7 @@ #include #include "agetpass.h" -#include "alloc/malloc.h" -#include "alloc/realloc.h" +#include "alloc/alloc.h" #include "chkname.h" #include "defines.h" /*@-exitarg@*/ diff --git a/src/newusers.c b/src/newusers.c index 1ee89347ef..7bd2e94054 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -32,7 +32,7 @@ #include #include -#include "alloc/reallocf.h" +#include "alloc/alloc.h" #include "atoi/a2i.h" #include "atoi/getnum.h" #include "attr.h" diff --git a/src/su.c b/src/su.c index cc74ab3a74..2e63f63255 100644 --- a/src/su.c +++ b/src/su.c @@ -46,7 +46,7 @@ #include #endif /* !USE_PAM */ -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "attr.h" #include "cast.h" #include "defines.h" diff --git a/src/useradd.c b/src/useradd.c index 25b7f4f3c9..bca4ab596a 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -31,7 +31,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/a2i.h" #include "atoi/getnum.h" #include "btrfs.h" diff --git a/src/usermod.c b/src/usermod.c index bd9dc82c64..e37813f235 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -29,7 +29,7 @@ #include #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "atoi/a2i.h" #include "atoi/getnum.h" #include "btrfs.h" diff --git a/tests/libsubid/04_nss/libsubid_zzz.c b/tests/libsubid/04_nss/libsubid_zzz.c index 2e929687ec..0e0333c1de 100644 --- a/tests/libsubid/04_nss/libsubid_zzz.c +++ b/tests/libsubid/04_nss/libsubid_zzz.c @@ -4,7 +4,9 @@ #include #include #include -#include "alloc/malloc.h" + +#include "alloc/alloc.h" + enum subid_status shadow_subid_has_any_range(const char *owner, enum subid_type t, bool *result) { diff --git a/tests/unit/test_chkname.c b/tests/unit/test_chkname.c index 56af7afa1e..dbc80e9a8e 100644 --- a/tests/unit/test_chkname.c +++ b/tests/unit/test_chkname.c @@ -17,7 +17,7 @@ #include // Required by #include -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include "chkname.h" #include "attr.h" diff --git a/tests/unit/test_exit_if_null.c b/tests/unit/test_exit_if_null.c index 28e285d3ac..1b2b7ef277 100644 --- a/tests/unit/test_exit_if_null.c +++ b/tests/unit/test_exit_if_null.c @@ -2,7 +2,7 @@ // SPDX-License-Identifier: BSD-3-Clause -#include "alloc/malloc.h" +#include "alloc/alloc.h" #include #include From 0471a346c44e43eb80cdb475b55f3d0f98e5b044 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 8 Sep 2026 19:44:42 +0200 Subject: [PATCH 6/7] lib/alloc/alloc.h: Further compact macros Get rid of the two layers of macros, and use just one. Signed-off-by: Alejandro Colomar --- lib/alloc/alloc.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/alloc/alloc.h b/lib/alloc/alloc.h index 793158ca43..084f84174d 100644 --- a/lib/alloc/alloc.h +++ b/lib/alloc/alloc.h @@ -17,24 +17,20 @@ // malloc_T - malloc type-safe -#define malloc_T(n, T) malloc_T_(n, typeas(T)) -#define malloc_T_(n, T) rvalue((T *){mallocarray(n, sizeof(T))}) +#define malloc_T(n, T) rvalue((typeas(T) *){mallocarray(n, sizeof(T))}) // calloc_T - calloc type-safe -#define calloc_T(n, T) calloc_T_(n, typeas(T)) -#define calloc_T_(n, T) rvalue((T *){calloc(n, sizeof(T))}) +#define calloc_T(n, T) rvalue((typeas(T) *){calloc(n, sizeof(T))}) // realloc_T - realloc type-safe -#define realloc_T(p, n, T) realloc_T_(p, n, typeas(T)) -#define realloc_T_(p, n, T) \ +#define realloc_T(p, n, T) \ ( \ - _Generic(p, T *: (void)0), \ - rvalue((T *){reallocarray_(p, n, sizeof(T))}) \ + _Generic(p, typeas(T) *: (void)0), \ + rvalue((typeas(T) *){reallocarray_(p, n, sizeof(T))}) \ ) // reallocf_T - realloc free-on-error type-safe -#define reallocf_T(p, n, T) reallocf_T_(p, n, typeas(T)) -#define reallocf_T_(p, n, T) \ +#define reallocf_T(p, n, T) \ ( \ - _Generic(p, T *: (void)0), \ - rvalue((T *){reallocarrayf_(p, n, sizeof(T))}) \ + _Generic(p, typeas(T) *: (void)0), \ + rvalue((typeas(T) *){reallocarrayf_(p, n, sizeof(T))}) \ ) From a5813017d3df23839394245b327ca9470d531cd9 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sat, 8 Aug 2026 13:44:08 +0200 Subject: [PATCH 7/7] lib/alloc/alloc.h: wsfix Align white space. Signed-off-by: Alejandro Colomar --- lib/alloc/alloc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/alloc/alloc.h b/lib/alloc/alloc.h index 084f84174d..c57e3831c0 100644 --- a/lib/alloc/alloc.h +++ b/lib/alloc/alloc.h @@ -35,9 +35,9 @@ // xmalloc_T - exit-on-error malloc type-safe -#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T)) +#define xmalloc_T(n, T) exit_if_null(malloc_T(n, T)) // xcalloc_T - exit-on-error calloc type-safe -#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T)) +#define xcalloc_T(n, T) exit_if_null(calloc_T(n, T)) // xrealloc_T - exit-on-error realloc type-safe #define xrealloc_T(p, n, T) exit_if_null(realloc_T(p, n, T)) @@ -46,7 +46,7 @@ #define mallocarray(...) reallocarray(NULL, __VA_ARGS__) -#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1) +#define reallocarray_(p, n, size) reallocarray(p, (n) ?: 1, (size) ?: 1) #define reallocarrayf_(p, n, size) reallocarrayf(p, (n) ?: 1, (size) ?: 1)