From f7c9406a0166b76a1d9e22e349613025facf5dec Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 22 Jun 2024 12:22:12 +0200 Subject: [PATCH] c-xvasprintf: Guarantee a non-NULL result. * lib/c-xvasprintf.h: Clarify the programmer's responsibilities. (c_xasprintf, c_xvasprintf): Declare as returning non-NULL. * lib/c-xvasprintf.c: Include , . (c_xvasprintf): Call c_vazsprintf instead of c_vasprintf. When some other error occurs, emit an error message and abort. * modules/c-xvasprintf (Files): Add m4/strerrorname_np.m4. (Depends-on): Add extensions, c-vazsprintf. Remove c-vasprintf. (configure.ac): Invoke gl_OPTIONAL_STRERRORNAME_NP. * NEWS: Mention the change. --- ChangeLog | 13 +++++++++++++ NEWS | 2 +- lib/c-xvasprintf.c | 33 +++++++++++++++++++++++++++++++-- lib/c-xvasprintf.h | 25 +++++++++++++++++-------- modules/c-xvasprintf | 7 +++++-- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3aec5b928..f81ae03de7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2024-06-22 Bruno Haible + + c-xvasprintf: Guarantee a non-NULL result. + * lib/c-xvasprintf.h: Clarify the programmer's responsibilities. + (c_xasprintf, c_xvasprintf): Declare as returning non-NULL. + * lib/c-xvasprintf.c: Include , . + (c_xvasprintf): Call c_vazsprintf instead of c_vasprintf. When some + other error occurs, emit an error message and abort. + * modules/c-xvasprintf (Files): Add m4/strerrorname_np.m4. + (Depends-on): Add extensions, c-vazsprintf. Remove c-vasprintf. + (configure.ac): Invoke gl_OPTIONAL_STRERRORNAME_NP. + * NEWS: Mention the change. + 2024-06-22 Bruno Haible c-vasprintf: Make return convention consistent with other modules. diff --git a/NEWS b/NEWS index 36ffbb64f8..4c5d9fc5de 100644 --- a/NEWS +++ b/NEWS @@ -75,7 +75,7 @@ User visible incompatible changes Date Modules Changes 2024-06-22 xvasprintf It is now the programmer's responsibility to pass - a valid format string without %ls, %lc directives + c-xvasprintf a valid format string without %ls, %lc directives and that all widths are >= -INT_MAX and <= INT_MAX. 2024-05-16 putenv This module is renamed to 'putenv-gnu'. diff --git a/lib/c-xvasprintf.c b/lib/c-xvasprintf.c index 0fda230eb9..b058bde4c5 100644 --- a/lib/c-xvasprintf.c +++ b/lib/c-xvasprintf.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include "c-vasprintf.h" #include "xalloc.h" @@ -30,11 +32,38 @@ c_xvasprintf (const char *format, va_list args) { char *result; - if (c_vasprintf (&result, format, args) < 0) + if (c_vazsprintf (&result, format, args) < 0) { if (errno == ENOMEM) xalloc_die (); - return NULL; + else + { + /* The programmer ought to have ensured that none of the other errors + can occur. */ + int err = errno; + char errbuf[20]; + const char *errname; +#if HAVE_WORKING_STRERRORNAME_NP + errname = strerrorname_np (err); + if (errname == NULL) +#else + if (err == EINVAL) + errname = "EINVAL"; + else if (err == EILSEQ) + errname = "EILSEQ"; + else if (err == EOVERFLOW) + errname = "EOVERFLOW"; + else +#endif + { + sprintf (errbuf, "%d", err); + errname = errbuf; + } + fprintf (stderr, "c_vasprintf failed! format=\"%s\", errno=%s\n", + format, errname); + fflush (stderr); + abort (); + } } return result; diff --git a/lib/c-xvasprintf.h b/lib/c-xvasprintf.h index 4cb4578584..897ecfdbf2 100644 --- a/lib/c-xvasprintf.h +++ b/lib/c-xvasprintf.h @@ -17,7 +17,8 @@ #ifndef _C_XVASPRINTF_H #define _C_XVASPRINTF_H -/* This file uses _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_MALLOC. */ +/* This file uses _GL_ATTRIBUTE_FORMAT, _GL_ATTRIBUTE_MALLOC, + _GL_ATTRIBUTE_RETURNS_NONNULL. */ #if !_GL_CONFIG_H_INCLUDED #error "Please include config.h first." #endif @@ -34,22 +35,30 @@ extern "C" { #endif -/* Write formatted output to a string dynamically allocated with malloc(), - and return it. Upon [ENOMEM] memory allocation error, call xalloc_die. - On some other error - - [EOVERFLOW] resulting string length is > INT_MAX, +/* Prints formatted output to a string dynamically allocated with malloc(), + and returns it. Upon [ENOMEM] memory allocation error, it calls xalloc_die. + + It is the responsibility of the programmer to ensure that + - the format string is valid, + - the format string does not use %ls or %lc directives, and + - all widths in the format string and passed as arguments are >= -INT_MAX + and <= INT_MAX, + so that other errors - [EINVAL] invalid format string, - [EILSEQ] error during conversion between wide and multibyte characters, - return NULL. + - [EOVERFLOW] some specified width is > INT_MAX, + cannot occur. Formatting takes place in the C locale, that is, the decimal point used in floating-point formatting directives is always '.'. */ extern char *c_xasprintf (const char *format, ...) _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 1, 2)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE; + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE + _GL_ATTRIBUTE_RETURNS_NONNULL; extern char *c_xvasprintf (const char *format, va_list args) _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 1, 0)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE; + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE + _GL_ATTRIBUTE_RETURNS_NONNULL; #ifdef __cplusplus } diff --git a/modules/c-xvasprintf b/modules/c-xvasprintf index b952128fb6..ccbc93d794 100644 --- a/modules/c-xvasprintf +++ b/modules/c-xvasprintf @@ -5,13 +5,16 @@ Files: lib/c-xvasprintf.h lib/c-xasprintf.c lib/c-xvasprintf.c +m4/strerrorname_np.m4 Depends-on: +extensions stdio -c-vasprintf +c-vazsprintf xalloc-die configure.ac: +gl_OPTIONAL_STRERRORNAME_NP Makefile.am: lib_SOURCES += c-xasprintf.c c-xvasprintf.c @@ -23,4 +26,4 @@ License: GPL Maintainer: -Ben Pfaff +all -- 2.39.5