From: Bruno Haible Date: Wed, 21 Feb 2024 10:14:21 +0000 (+0100) Subject: intl: Annotate *printf functions with __attribute__ __format__. X-Git-Tag: v0.22.5~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eef429bbccbff2bca08bafc2ff76f7ec2be93d2a;p=thirdparty%2Fgettext.git intl: Annotate *printf functions with __attribute__ __format__. Reported by Pierre Ossman at . * gettext-runtime/intl/libgnuintl.in.h (_INTL_ATTRIBUTE_FORMAT, _INTL_ATTRIBUTE_SPEC_PRINTF_STANDARD, _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD): New macros. (fprintf, vfprintf, printf, vprintf, sprintf, vsprintf, snprintf, vsnprintf, asprintf, vasprintf): Annotate with _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD. * gettext-runtime/intl/printf.c: Update comment. * gettext-runtime/NEWS: Mention this change. * NEWS: Likewise. --- diff --git a/NEWS b/NEWS index a525eb62b..035f2cda5 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +Version 0.22.5 - February 2024 + +* The replacements for the printf()/fprintf()/... functions that are + provided through on native Windows and NetBSD now enable + GCC's format string analysis (-Wformat). + Version 0.22.4 - November 2023 * Bug fixes: diff --git a/gettext-runtime/NEWS b/gettext-runtime/NEWS index 48d245778..5fc1ac3ca 100644 --- a/gettext-runtime/NEWS +++ b/gettext-runtime/NEWS @@ -1,3 +1,9 @@ +Version 0.22.5 - February 2024 + +* The replacements for the printf()/fprintf()/... functions that are + provided through on native Windows and NetBSD now enable + GCC's format string analysis (-Wformat). + Version 0.22.3 - October 2023 * Portability: diff --git a/gettext-runtime/intl/libgnuintl.in.h b/gettext-runtime/intl/libgnuintl.in.h index e8642a783..359f85fb8 100644 --- a/gettext-runtime/intl/libgnuintl.in.h +++ b/gettext-runtime/intl/libgnuintl.in.h @@ -1,5 +1,5 @@ /* Message catalogs for internationalization. - Copyright (C) 1995-1997, 2000-2016, 2018-2023 Free Software Foundation, Inc. + Copyright (C) 1995-1997, 2000-2016, 2018-2024 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -117,6 +117,41 @@ extern int libintl_version; # define _INTL_MAY_RETURN_STRING_ARG(n) #endif +/* _INTL_ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) + declares that the STRING-INDEXth function argument is a format string of + style ARCHETYPE, which is one of: + printf, gnu_printf + scanf, gnu_scanf, + strftime, gnu_strftime, + strfmon, + or the same thing prefixed and suffixed with '__'. + If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK + are suitable for the format string. */ +/* Applies to: functions. */ +#if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 7) > 2) || defined __clang__ +# define _INTL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +#else +# define _INTL_ATTRIBUTE_FORMAT(spec) +#endif + +/* _INTL_ATTRIBUTE_SPEC_PRINTF_STANDARD + An __attribute__ __format__ specifier for a function that takes a format + string and arguments, where the format string directives are the ones + standardized by ISO C99 and POSIX. */ +/* __gnu_printf__ is supported in GCC >= 4.4. */ +#if defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 4) > 4 +# define _INTL_ATTRIBUTE_SPEC_PRINTF_STANDARD __gnu_printf__ +#else +# define _INTL_ATTRIBUTE_SPEC_PRINTF_STANDARD __printf__ +#endif + +/* _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#define _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(formatstring_parameter, first_argument) \ + _INTL_ATTRIBUTE_FORMAT ((_INTL_ATTRIBUTE_SPEC_PRINTF_STANDARD, formatstring_parameter, first_argument)) + /* Look up MSGID in the current default message catalog for the current LC_MESSAGES locale. If not found, returns MSGID itself (the default text). */ @@ -369,7 +404,8 @@ extern char *bind_textdomain_codeset (const char *__domainname, # if !((defined fprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_fprintf) /* don't override gnulib */ # undef fprintf # define fprintf libintl_fprintf -extern int fprintf (FILE *, const char *, ...); +extern int fprintf (FILE *, const char *, ...) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_fprintf; } # endif @@ -377,7 +413,8 @@ namespace std { using ::libintl_fprintf; } # if !((defined vfprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_vfprintf) /* don't override gnulib */ # undef vfprintf # define vfprintf libintl_vfprintf -extern int vfprintf (FILE *, const char *, va_list); +extern int vfprintf (FILE *, const char *, va_list) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_vfprintf; } # endif @@ -398,7 +435,8 @@ namespace std { using ::libintl_vfprintf; } # define libintl_printf __printf__ # endif # define printf libintl_printf -extern int printf (const char *, ...); +extern int printf (const char *, ...) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_printf; } # endif @@ -406,7 +444,8 @@ namespace std { using ::libintl_printf; } # if !((defined vprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_vprintf) /* don't override gnulib */ # undef vprintf # define vprintf libintl_vprintf -extern int vprintf (const char *, va_list); +extern int vprintf (const char *, va_list) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_vprintf; } # endif @@ -415,7 +454,8 @@ namespace std { using ::libintl_vprintf; } # if !((defined sprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_sprintf) /* don't override gnulib */ # undef sprintf # define sprintf libintl_sprintf -extern int sprintf (char *, const char *, ...); +extern int sprintf (char *, const char *, ...) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_sprintf; } # endif @@ -423,7 +463,8 @@ namespace std { using ::libintl_sprintf; } # if !((defined vsprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_vsprintf) /* don't override gnulib */ # undef vsprintf # define vsprintf libintl_vsprintf -extern int vsprintf (char *, const char *, va_list); +extern int vsprintf (char *, const char *, va_list) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_vsprintf; } # endif @@ -434,7 +475,8 @@ namespace std { using ::libintl_vsprintf; } # if !((defined snprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_snprintf) /* don't override gnulib */ # undef snprintf # define snprintf libintl_snprintf -extern int snprintf (char *, size_t, const char *, ...); +extern int snprintf (char *, size_t, const char *, ...) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_snprintf; } # endif @@ -442,7 +484,8 @@ namespace std { using ::libintl_snprintf; } # if !((defined vsnprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_vsnprintf) /* don't override gnulib */ # undef vsnprintf # define vsnprintf libintl_vsnprintf -extern int vsnprintf (char *, size_t, const char *, va_list); +extern int vsnprintf (char *, size_t, const char *, va_list) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_vsnprintf; } # endif @@ -455,7 +498,8 @@ namespace std { using ::libintl_vsnprintf; } # if !((defined asprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_asprintf) /* don't override gnulib */ # undef asprintf # define asprintf libintl_asprintf -extern int asprintf (char **, const char *, ...); +extern int asprintf (char **, const char *, ...) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_asprintf; } # endif @@ -463,7 +507,8 @@ namespace std { using ::libintl_asprintf; } # if !((defined vasprintf && defined _GL_STDIO_H) || defined GNULIB_overrides_vasprintf) /* don't override gnulib */ # undef vasprintf # define vasprintf libintl_vasprintf -extern int vasprintf (char **, const char *, va_list); +extern int vasprintf (char **, const char *, va_list) + _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0); # if defined __cplusplus && !defined _INTL_CXX_NO_CLOBBER_STD_NAMESPACE namespace std { using ::libintl_vasprintf; } # endif diff --git a/gettext-runtime/intl/printf.c b/gettext-runtime/intl/printf.c index 836cc0732..65a8edc2b 100644 --- a/gettext-runtime/intl/printf.c +++ b/gettext-runtime/intl/printf.c @@ -1,5 +1,5 @@ /* Formatted output to strings, using POSIX/XSI format strings with positions. - Copyright (C) 2003, 2006-2007, 2009-2011, 2018, 2020-2023 Free Software Foundation, Inc. + Copyright (C) 2003, 2006-2007, 2009-2011, 2018, 2020-2024 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software: you can redistribute it and/or modify @@ -121,7 +121,9 @@ char *alloca (); /* Users don't expect libintl_fprintf to be less POSIX compliant than the fprintf implementation provided by gnulib or - on mingw - the one provided by mingw libs when __USE_MINGW_ANSI_STDIO is in - effect. */ + effect. + This definition is necessary, so that libgnuintl.h can declare + the *printf functions with _INTL_ATTRIBUTE_FORMAT_PRINTF_STANDARD. */ #define USE_REPLACEMENT_CODE_ALWAYS 1 DLL_EXPORTED