[PATCH v2] assert: Refactor assert/assert_perror

Florian Weimer fweimer@redhat.com
Mon Aug 18 14:01:00 GMT 2025


* Adhemerval Zanella:

> It now calls __libc_assert_message, which contains similar logic. The
> assert now does not require any dynamic memory allocation, so
> test-assert2.c is adapted to handle it.
>
> It also removes the fxprintf from assert/assert_perror; although it
> is not 100% backwards-compatible (write message only if there is a
> file descriptor associated with the stderr) it nows write bytes
> directly to without going through the wide stream state.
>
> Checked on aarch64-linux-gnu.
> --
> Changes from v1:
> * Setup the VMA properly.
> ---
>  assert/__libc_assert_fail.c |   4 +-
>  assert/assert-perr.c        |  22 ++++++-
>  assert/assert.c             | 112 +++++-------------------------------
>  assert/test-assert-2.c      |  18 ++----
>  include/stdio.h             |  51 ++++++++++++----
>  sysdeps/posix/libc_fatal.c  |   4 +-
>  6 files changed, 82 insertions(+), 129 deletions(-)
>
> diff --git a/assert/__libc_assert_fail.c b/assert/__libc_assert_fail.c
> index b50637a893..2d4654bd41 100644
> --- a/assert/__libc_assert_fail.c
> +++ b/assert/__libc_assert_fail.c
> @@ -28,6 +28,6 @@ __libc_assert_fail (const char *assertion, const char *file, unsigned int line,
>    char linebuf[INT_BUFSIZE_BOUND (unsigned int)];
>    array_end (linebuf)[-1] = '\0';
>    char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0);
> -  __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n",
> -                  file, linestr, function, assertion);
> +  __libc_assert_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n",
> +			 file, linestr, function, assertion);
>  }

I think we are aiming for 79 characters at maximum per line.

> diff --git a/include/stdio.h b/include/stdio.h
> index e48d709919..683b212d14 100644
> --- a/include/stdio.h
> +++ b/include/stdio.h
> @@ -171,33 +171,64 @@ extern void __fortify_fail (const char *msg) __attribute__ ((__noreturn__));
>  libc_hidden_proto (__fortify_fail)
>  
>  /* The maximum number of varargs allowed in a __libc_message format string */
> -#define LIBC_MESSAGE_MAX_ARGS 4
> +#define LIBC_MESSAGE_MAX_ARGS 7
>  
> -_Noreturn void __libc_message_impl (const char *__fnt, ...) attribute_hidden
> -     __attribute__ ((__format__ (__printf__, 1, 2)));
> +_Noreturn void __libc_message_impl (const char *__vmaname, const char *__fmt,
> +				    ...) attribute_hidden
> +     __attribute__ ((__format__ (__printf__, 2, 3)));
> +
> +#define __libc_fatal_vma_name  "glibc: fatal"
> +#define __libc_assert_vma_name "glibc: assert"
>  
>  #define __libc_message0(fmt) \
> -   __libc_message_impl (fmt)
> +   __libc_message_impl (__libc_fatal_vma_name, fmt)
>  #define __libc_message1(fmt, a1) \
> -   __libc_message_impl (fmt, a1)
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1)
>  #define __libc_message2(fmt, a1, a2) \
> -   __libc_message_impl (fmt, a1, a2)
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2)
>  #define __libc_message3(fmt, a1, a2, a3) \
> -   __libc_message_impl (fmt, a1, a2, a3)
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2, a3)
>  #define __libc_message4(fmt, a1, a2, a3, a4) \
> -   __libc_message_impl (fmt, a1, a2, a3, a4)
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2, a3, a4)
> +#define __libc_message5(fmt, a1, a2, a3, a4, a5) \
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2, a3, a4, a5)
> +#define __libc_message6(fmt, a1, a2, a3, a4, a5, a6) \
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2, a3, a4, a5, a6)
> +#define __libc_message7(fmt, a1, a2, a3, a4, a5, a6, a7) \
> +   __libc_message_impl (__libc_fatal_vma_name, fmt, a1, a2, a3, a4, a5, a6, a7)
> +
> +#define __libc_assert_message0(fmt) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt)
> +#define __libc_assert_message1(fmt, a1) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1)
> +#define __libc_assert_message2(fmt, a1, a2) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2)
> +#define __libc_assert_message3(fmt, a1, a2, a3) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2, a3)
> +#define __libc_assert_message4(fmt, a1, a2, a3, a4) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2, a3, a4)
> +#define __libc_assert_message5(fmt, a1, a2, a3, a4, a5) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2, a3, a4, a5)
> +#define __libc_assert_message6(fmt, a1, a2, a3, a4, a5, a6) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2, a3, a4, a5, a6)
> +#define __libc_assert_message7(fmt, a1, a2, a3, a4, a5, a6, a7) \
> +   __libc_message_impl (__libc_assert_vma_name, fmt, a1, a2, a3, a4, a5, a6, a7)
>  
>  #define __libc_message_concat_x(a,b)  a##b
>  #define __libc_message_concat(a,b)    __libc_message_concat_x (a, b)
>  
> -#define __libc_message_nargs_x(a0,a1,a2,a3,a4,a5,a6,...) a6
> +#define __libc_message_nargs_x(a0,a1,a2,a3,a4,a5,a6,a7,...) a7
>  #define __libc_message_nargs(b, ...) \
> -   __libc_message_nargs_x (__VA_ARGS__,6,5,4,3,2,1,0,)
> +   __libc_message_nargs_x (__VA_ARGS__,7,6,5,4,3,2,1,0,)
>  #define __libc_message_disp(b, ...) \
>     __libc_message_concat (b, __libc_message_nargs (__VA_ARGS__))(__VA_ARGS__)

Why do we need __libc_message_nargs when things go into a varargs
function without an explicit argument count in the end anyway?

The patch no longer applies to the main branch.

Thanks,
Florian



More information about the Libc-alpha mailing list