+2025-05-28 Bruno Haible <bruno@clisp.org>
+
+ gettext-h: Avoid gcc -Wformat-security warnings with --disable-nls.
+ Reported by Holger Hoffstätte <holger@applied-asynchrony.com> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2025-05/msg00225.html>.
+ * lib/gettext.h (gettext, dgettext, dcgettext): With gcc in C mode,
+ define these as inline functions.
+ * lib/sigpipe-die.c (sigpipe_die): Use translated string as a format
+ string, relying on the format string checking done by 'msgfmt -c'.
+ * lib/xmemcoll.c (collate_error): Revert commit from 2025-01-17.
+ * lib/xprintf.c (xvprintf, xvfprintf): Likewise.
+ * lib/openat-die.c (openat_save_fail, openat_restore_fail): Revert
+ commit from 2024-12-10.
+
2025-05-27 Bruno Haible <bruno@clisp.org>
stddef-h: Make 'unreachable' usable in C++ mode.
# endif
# endif
-/* Disabled NLS.
- The casts to 'const char *' serve the purpose of producing warnings
- for invalid uses of the value returned from these functions.
- On pre-ANSI systems without 'const', the config.h file is supposed to
- contain "#define const". */
-# undef gettext
-# define gettext(Msgid) ((const char *) (Msgid))
-# undef dgettext
-# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
-# undef dcgettext
-# define dcgettext(Domainname, Msgid, Category) \
- ((void) (Category), dgettext (Domainname, Msgid))
+/* Disabled NLS. */
+# if defined __GNUC__ && !defined __clang__ && !defined __cplusplus
+/* Use inline functions, to avoid warnings
+ warning: format not a string literal and no format arguments
+ that don't occur with enabled NLS. */
+__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
+const char *
+gettext (const char *msgid)
+{
+ return msgid;
+}
+__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
+const char *
+dgettext (const char *domain, const char *msgid)
+{
+ (void) domain;
+ return msgid;
+}
+__attribute__ ((__always_inline__, __gnu_inline__)) extern inline
+const char *
+dcgettext (const char *domain, const char *msgid, int category)
+{
+ (void) domain;
+ (void) category;
+ return msgid;
+}
+# else
+/* The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions. */
+# undef gettext
+# define gettext(Msgid) ((const char *) (Msgid))
+# undef dgettext
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# undef dcgettext
+# define dcgettext(Domainname, Msgid, Category) \
+ ((void) (Category), dgettext (Domainname, Msgid))
+# endif
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \
openat_save_fail (int errnum)
{
#ifndef GNULIB_LIBPOSIX
- error (exit_failure, errnum, "%s",
+ error (exit_failure, errnum,
_("unable to record current working directory"));
#endif
/* _Noreturn cannot be applied to error, since it returns
openat_restore_fail (int errnum)
{
#ifndef GNULIB_LIBPOSIX
- error (exit_failure, errnum, "%s",
+ error (exit_failure, errnum,
_("failed to return to initial working directory"));
#endif
void
sigpipe_die (void)
{
- error (exit_failure, 0, "%s",
+ error (exit_failure, 0,
_("error writing to a closed pipe or socket"));
/* Ensure that this function really does not return. */
char const *s1, size_t s1len,
char const *s2, size_t s2len)
{
- error (0, collation_errno, "%s", _("string comparison failed"));
- error (0, 0, "%s", _("Set LC_ALL='C' to work around the problem."));
+ error (0, collation_errno, _("string comparison failed"));
+ error (0, 0, _("Set LC_ALL='C' to work around the problem."));
error (exit_failure, 0,
_("The strings compared were %s and %s."),
quotearg_n_style_mem (0, locale_quoting_style, s1, s1len),
{
off64_t retval = vzprintf (format, args);
if (retval < 0 && ! ferror (stdout))
- error (exit_failure, errno, "%s", _("cannot perform formatted output"));
+ error (exit_failure, errno, _("cannot perform formatted output"));
return retval;
}
{
off64_t retval = vfzprintf (stream, format, args);
if (retval < 0 && ! ferror (stream))
- error (exit_failure, errno, "%s", _("cannot perform formatted output"));
+ error (exit_failure, errno, _("cannot perform formatted output"));
return retval;
}