From 962b0d07cd0b6f8d361182c47811a403ea227e8d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 6 Sep 2026 16:01:28 -0700 Subject: [PATCH] Update from Gnulib by running admin/merge-gnulib --- doc/misc/texinfo.tex | 123 +++++++++++++--- lib/acl-internal.c | 22 +-- lib/acl-internal.h | 10 +- lib/canonicalize-lgpl.c | 8 +- lib/diffseq.h | 6 +- lib/dirent.in.h | 2 +- lib/eloop-threshold.h | 88 ------------ lib/fpending.h | 2 +- lib/getopt1.c | 2 +- lib/gettext.h | 289 ++++++++++++++++++++++++++------------ lib/gnulib.mk.in | 2 +- lib/memrchr.c | 2 +- lib/min-eloop-threshold.h | 42 ++++++ lib/nproc.c | 12 +- lib/rawmemchr.c | 30 ++-- lib/readutmp.h | 8 +- lib/realloc.c | 9 -- lib/regex_internal.c | 4 +- lib/strftime.c | 11 +- lib/string.in.h | 27 ++-- lib/time.in.h | 6 +- lib/verify.h | 18 ++- m4/getopt.m4 | 13 +- m4/gnulib-common.m4 | 2 - m4/gnulib-comp.m4 | 2 +- m4/malloc.m4 | 31 +++- m4/readutmp.m4 | 18 ++- src/image.c | 4 +- 28 files changed, 507 insertions(+), 286 deletions(-) delete mode 100644 lib/eloop-threshold.h create mode 100644 lib/min-eloop-threshold.h diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 7187edf08e7..bf97258fcb3 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2026-07-04.10} +\def\texinfoversion{2026-08-13.21} % % Copyright 1985, 1986, 1988, 1990-2026 Free Software Foundation, Inc. % @@ -153,6 +153,9 @@ \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi +% scratch count register +\newcount\countA + % Give the space character the catcode for a space. \def\spaceisspace{\catcode`\ =10\relax} @@ -765,7 +768,7 @@ % @include FILE -- \input text of FILE. % -\def\include{\tracingmacros=1\parseargusing\filenamecatcodes\includezzz} +\def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% @@ -997,7 +1000,6 @@ \newtoks\toksD \newbox\boxA \newbox\boxB -\newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest @@ -9162,7 +9164,9 @@ % type (Ynumbered, Yappendix, Ynothing). #2 is the section title. % \def\donoderef#1#2{% - \ifx\lastnode\empty\else + \ifx\lastnode\empty + \setrefshadow{#1}{#2}% + \else \setref{\lastnode}{#1}{#2}% \global\let\lastnode=\empty \setnodeseenonce @@ -9207,6 +9211,9 @@ % \def\setref#1#2#3{% \pdfmkdest{#1}% + \dosetref{#1}{#2}{#3}{xrdef}% +} +\def\dosetref#1#2#3#4{% \iflinks {% \requireauxfile @@ -9214,17 +9221,28 @@ % match definition in \xrdef, \refx, \xrefX. \def\value##1{##1}% \edef\writexrdef##1##2{% - \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + \write\auxfile{@#4{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = {#3}% \immediate \writexrdef{title}{\the\toks0 }% - \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. - \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout + \immediate \writexrdef{snt}{\csname #2\endcsname}% + \safewhatsit{\writexrdef{pg}{\folio}}% }% \fi } +% Similar to \setref, but used for targets created by sectioning commands. +% Write information about this target using @xrshad instead of @xrdef. +\def\setrefshadow#1#2{% + % For PDF, output the target with \pdfdest. Note pdfTeX issues a warning + % if we output two targets with the same name. + \pdfmkdest{\pdfshadowprefix#2}% + \dosetref{#2}{#1}{#2}{xrshad}% +} + +\def\pdfshadowprefix{XXSHADOW-} + % @xrefautosectiontitle on|off says whether @section(ing) names are used % automatically in xrefs, if the third arg is not explicitly specified. % This was provided as a "secret" @set xref-automatic-section-title @@ -9270,7 +9288,17 @@ \def\infofilename{\ignorespaces #4}% \setbox\infofilenamebox = \hbox{\infofilename\unskip}% % - \startxreflink{#1}{#4}% + \ifdim \wd\printedmanualbox = 0pt + \checkshadowactive{#1}\countA + \expandafter\ifnum\countA = 1 + \startxreflink{\pdfshadowprefix#1}{}% + \else + \startxreflink{#1}{}% + \fi + \else + \startxreflink{#1}{#4}% + \fi + % \getrefx{#1-title}\Xthisreftitle % % Float references are printed completely differently: "Figure 1.2" @@ -9536,31 +9564,62 @@ \fi } +\def\xrdefctxt{% + % Context for expanding the node or anchor name to remove control sequences. + % \turnoffactive stops 8-bit characters being changed to commands + % like @'e. + \indexnofonts + \turnoffactive + \def\value##1{##1}% +} + % Set #2 to xref string #1 \def\getrefx#1#2{% \requireauxfile {% - \indexnofonts - \turnoffactive - \def\value##1{##1}% + \xrdefctxt \expandafter\global\expandafter\let\expandafter#2\csname XR#1\endcsname + \ifx#2\relax + % try a shadow definition + \expandafter\global\expandafter\let\expandafter#2\csname SXR#1\endcsname + \ifx#2\empty + \let#2\relax + \fi + \fi }% } +% Check if shadow definitions are active for target name #1, setting the +% count register sequence in #2 to 1 if so. +\def\checkshadowactive#1#2{% + \requireauxfile + {% + \xrdefctxt + \expandafter\global\expandafter\let\expandafter\tmp\csname SXR#1-title\endcsname + }% + \ifx\tmp\relax + #2=0 % no definitions made + \else + \ifx\tmp\empty + #2=0 % shadow definitions were disabled + \else + \expandafter\let\expandafter\tmp\csname XR#1-title\endcsname + \ifx\tmp\relax + #2=1 % yes, shadow definitions are active + \else + #2=0 % no, a real definition was made. + \fi + \fi + \fi +}% + % This is the macro invoked by entries in the aux file. Define a control % sequence for a cross-reference target (we prepend XR to the control sequence % name to avoid collisions). The value is the page number. If this is a float % type, we have more work to do. % \def\xrdef#1#2{% - {% Expand the node or anchor name to remove control sequences. - % \turnoffactive stops 8-bit characters being changed to commands - % like @'e. \refx does the same to retrieve the value in the definition. - \indexnofonts - \turnoffactive - \def\value##1{##1}% - \xdef\safexrefname{#1}% - }% + {\xrdefctxt \xdef\safexrefname{#1}}% % \bgroup \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% @@ -9592,6 +9651,24 @@ \ignorespaces % ignore ends of line in aux file } +% Like \xrdef, but used for "shadow" definitions. +\def\xrshad#1#2{% + {\xrdefctxt \xdef\safexrefname{#1}}% + \bgroup + \expandafter\ifx\csname XR\safexrefname\endcsname\relax + \expandafter\ifx\csname SXR\safexrefname\endcsname\relax + % safe to make shadow definition. + \expandafter\gdef\csname SXR\safexrefname\endcsname{#2}% + \else + % earlier shadow definition. disable. + \expandafter\gdef\csname SXR\safexrefname\endcsname{}% + \fi + \else + % blocked by node or anchor definition + \fi + \egroup +} + % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate at the beginning of the file. @@ -9988,6 +10065,14 @@ % We can't be used inside a paragraph. \par % + % Allow a page break with a ragged page bottom. This could help to reduce + % interparagraph spacing if a large float doesn't fit on the current page. + % + \penalty 0 + \vskip 0pt plus 5\baselineskip + \penalty 1000 + \vskip 0pt plus -5\baselineskip + % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% diff --git a/lib/acl-internal.c b/lib/acl-internal.c index 7603abed687..e012cc64bbf 100644 --- a/lib/acl-internal.c +++ b/lib/acl-internal.c @@ -159,11 +159,11 @@ acl_default_nontrivial (acl_t acl) Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ int -acl_nontrivial (int count, aclent_t *entries) +acl_nontrivial (int count, aclent_t const *entries) { for (int i = 0; i < count; i++) { - aclent_t *ace = &entries[i]; + aclent_t const *ace = &entries[i]; /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). @@ -188,7 +188,7 @@ acl_nontrivial (int count, aclent_t *entries) Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ int -acl_ace_nontrivial (int count, ace_t *entries) +acl_ace_nontrivial (int count, ace_t const *entries) { /* The flags in the ace_t structure changed in a binary incompatible way when ACL_NO_TRIVIAL etc. were introduced in version 1.15. @@ -209,7 +209,7 @@ acl_ace_nontrivial (int count, ace_t *entries) /* Running on Solaris 10. */ for (int i = 0; i < count; i++) { - ace_t *ace = &entries[i]; + ace_t const *ace = &entries[i]; /* Note: If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat(). @@ -236,7 +236,7 @@ acl_ace_nontrivial (int count, ace_t *entries) for (int i = 0; i < count; i++) { - ace_t *ace = &entries[i]; + ace_t const *ace = &entries[i]; unsigned int index1; if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE) @@ -368,14 +368,14 @@ acl_ace_nontrivial (int count, ace_t *entries) /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ int -acl_nontrivial (int count, struct acl_entry *entries) +acl_nontrivial (int count, struct acl_entry const *entries) { if (count > 3) return 1; for (int i = 0; i < count; i++) { - struct acl_entry *ace = &entries[i]; + struct acl_entry const *ace = &entries[i]; if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP) return 1; @@ -388,11 +388,11 @@ acl_nontrivial (int count, struct acl_entry *entries) /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ int -aclv_nontrivial (int count, struct acl *entries) +aclv_nontrivial (int count, struct acl const *entries) { for (int i = 0; i < count; i++) { - struct acl *ace = &entries[i]; + struct acl const *ace = &entries[i]; /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). @@ -471,11 +471,11 @@ acl_nfs4_nontrivial (nfs4_acl_int_t *a) Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ int -acl_nontrivial (int count, struct acl *entries) +acl_nontrivial (int count, struct acl const *entries) { for (int i = 0; i < count; i++) { - struct acl *ace = &entries[i]; + struct acl const *ace = &entries[i]; /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). diff --git a/lib/acl-internal.h b/lib/acl-internal.h index eafb4d027fb..36be1f657dd 100644 --- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -156,14 +156,14 @@ extern int acl_default_nontrivial (acl_t); /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE; +extern int acl_nontrivial (int count, aclent_t const *entries) _GL_ATTRIBUTE_PURE; # ifdef ACE_GETACL /* Solaris 10 */ /* Test an ACL retrieved with ACE_GETACL. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE; +extern int acl_ace_nontrivial (int count, ace_t const *entries) _GL_ATTRIBUTE_PURE; /* Definitions for when the built executable is executed on Solaris 10 (newer version) or Solaris 11. */ @@ -202,13 +202,13 @@ extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE; /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, struct acl_entry *entries); +extern int acl_nontrivial (int count, struct acl_entry const *entries); # if HAVE_ACLV_H /* HP-UX >= 11.11 */ /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int aclv_nontrivial (int count, struct acl *entries); +extern int aclv_nontrivial (int count, struct acl const *entries); # endif @@ -226,7 +226,7 @@ extern int acl_nontrivial (struct acl *a); /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, struct acl *entries); +extern int acl_nontrivial (int count, struct acl const *entries); # endif diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c index a87d46a4339..92c96243c23 100644 --- a/lib/canonicalize-lgpl.c +++ b/lib/canonicalize-lgpl.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include @@ -42,6 +42,7 @@ #ifdef _LIBC # include +# include # define GCC_LINT 1 # define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) #else @@ -72,7 +73,6 @@ # endif # define __mempcpy mempcpy # define __pathconf pathconf -# define __rawmemchr rawmemchr # define __readlink readlink # if IN_RELOCWRAPPER /* When building the relocatable program wrapper, use the system's memmove @@ -233,7 +233,7 @@ realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs) return NULL; rname = bufs->rname.data; } - dest = __rawmemchr (rname, '\0'); + dest = strchr (rname, '\0'); start = name; prefix_len = FILE_SYSTEM_PREFIX_LEN (rname); } @@ -317,7 +317,7 @@ realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs) } if (0 <= n) { - if (++num_links > __eloop_threshold ()) + if (++num_links > MIN_ELOOP_THRESHOLD) { __set_errno (ELOOP); goto error; diff --git a/lib/diffseq.h b/lib/diffseq.h index 73fa47b42e1..677dacc0aef 100644 --- a/lib/diffseq.h +++ b/lib/diffseq.h @@ -99,11 +99,13 @@ #endif /* Suppress gcc's "...may be used before initialized" warnings, - generated by GCC versions up to at least GCC 15.1. + generated by GCC versions before GCC 17 (GCC bug 80922). Likewise for gcc -fanalyzer's "use of uninitialized value" warnings. */ #if _GL_GNUC_PREREQ (4, 7) # pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# if __GNUC__ < 17 +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# endif # if _GL_GNUC_PREREQ (13, 0) # pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value" # endif diff --git a/lib/dirent.in.h b/lib/dirent.in.h index 9198c1d3087..0a32637b8a6 100644 --- a/lib/dirent.in.h +++ b/lib/dirent.in.h @@ -367,7 +367,7 @@ _GL_WARN_ON_USE (scandir, "scandir is unportable - " /* Compare two 'struct dirent' entries alphabetically. */ # if !@HAVE_ALPHASORT@ _GL_FUNCDECL_SYS (alphasort, int, - (const struct dirent **, const struct dirent **), + (const struct dirent * /*const*/ *, const struct dirent * /*const*/ *), _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2))); # endif diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h deleted file mode 100644 index 3e33a247089..00000000000 --- a/lib/eloop-threshold.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Threshold at which to diagnose ELOOP. Generic version. - Copyright (C) 2012-2026 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifndef _ELOOP_THRESHOLD_H -#define _ELOOP_THRESHOLD_H 1 - -/* This file uses _GL_ATTRIBUTE_CONST. */ -#if !_LIBC && !_GL_CONFIG_H_INCLUDED - #error "Please include config.h first." -#endif - -#include -#ifdef _LIBC -# include -# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) -#else -# include -# include "minmax.h" -# define __sysconf sysconf -# if (!defined SYMLOOP_MAX \ - && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX)) -# define SYMLOOP_MAX 8 -# endif -#endif - -/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic - links that can be reliably traversed in the resolution of a - pathname in the absence of a loop." This makes it a minimum that - we should certainly accept. But it leaves open the possibility - that more might sometimes work--just not "reliably". - - For example, Linux implements a complex policy whereby there is a - small limit on the number of direct symlink traversals (a symlink - to a symlink to a symlink), but larger limit on the total number of - symlink traversals overall. Hence the SYMLOOP_MAX number should be - the small one, but the limit library functions enforce on users - should be the larger one. - - So, we use the larger of the reported SYMLOOP_MAX (if any) and our - own constant MIN_ELOOP_THRESHOLD, below. This constant should be - large enough that it never rules out a file name and directory tree - that the underlying system (i.e. calls to 'open' et al) would - resolve successfully. It should be small enough that actual loops - are detected without a huge number of iterations. */ - -#ifndef MIN_ELOOP_THRESHOLD -# define MIN_ELOOP_THRESHOLD 40 -#endif - -/* Return the maximum number of symlink traversals to permit - before diagnosing ELOOP. */ -static inline unsigned int _GL_ATTRIBUTE_CONST -__eloop_threshold (void) -{ -#ifdef SYMLOOP_MAX - const int symloop_max = SYMLOOP_MAX; -#else - /* The function is marked 'const' even though we use memory and - call a function, because sysconf is required to return the - same value in every call and so it must always be safe to - call __eloop_threshold exactly once and reuse the value. */ - static long int sysconf_symloop_max; - if (sysconf_symloop_max == 0) - sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX); - const unsigned int symloop_max = (sysconf_symloop_max <= 0 - ? _POSIX_SYMLOOP_MAX - : sysconf_symloop_max); -#endif - - return MAX (symloop_max, MIN_ELOOP_THRESHOLD); -} - -#endif /* eloop-threshold.h */ diff --git a/lib/fpending.h b/lib/fpending.h index aeb1d9310d8..dd4e74b750d 100644 --- a/lib/fpending.h +++ b/lib/fpending.h @@ -36,7 +36,7 @@ extern "C" { #if !HAVE_DECL___FPENDING -size_t __fpending (FILE *) _GL_ATTRIBUTE_PURE; +size_t __fpending (FILE /*const*/ *) _GL_ATTRIBUTE_PURE; #endif diff --git a/lib/getopt1.c b/lib/getopt1.c index 7a5ae1cad07..c127c627ee5 100644 --- a/lib/getopt1.c +++ b/lib/getopt1.c @@ -25,7 +25,7 @@ #include "getopt_int.h" /* Convert char *__getopt_argv_const * to char ** without provoking - gcc -Wuseless-cast when __getopt_argv_gconst is empty. */ + gcc -Wuseless-cast when __getopt_argv_const is empty. */ #ifdef __getopt_argv_const_is_empty # define ARGV_CAST(argv) (argv) #else diff --git a/lib/gettext.h b/lib/gettext.h index 02b8b7b8de4..2f4b1c9d864 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -42,9 +42,7 @@ /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ + as well because people using "gettext.h" will not include . */ # if defined(__sun) # include # endif @@ -59,52 +57,68 @@ # endif # endif +/* Like the C cast ((type) (expr)), but do only conversions that an + ordinary assignment would do. This can diagnose invalid arguments + better than a cast would. */ +# ifdef __cplusplus +# define _LIBGETTEXT_FUNCAST(type, expr) static_cast (expr) +# else +# define _LIBGETTEXT_FUNCAST(type, expr) (type) {(expr)} +# endif + /* Disabled NLS. */ -/* When gcc is used with option -Wformat=2, we need to silence - "warning: format not a string literal, argument types not checked [-Wformat-nonliteral]" +/* When gcc or clang is used with option -Wformat=2, we need to silence + gcc: "warning: format not a string literal, argument types not checked [-Wformat-nonliteral]" + clang: "warning: format string is not a string literal [-Wformat-nonliteral]", + "warning: format string is not a string literal (potentially insecure) [-Wformat-security]" warnings that would occur at every invocation of a *gettext function in a *printf format string position. - Do this with inline functions when possible, namely for gettext, dgettext, - dcgettext, which are known to gcc as "external built-ins". - It is not ideal to ignore the possible side effects done in the - Domainname and Category arguments, but it's better than to have a - warning at every invocation in a format string position. */ -/* When clang is used with option -Wformat=2, we need to silence - "warning: format string is not a string literal [-Wformat-nonliteral]" - warnings that would occur at every invocation of a *gettext function - in a *printf format string position. - It is not ideal to ignore the possible side effects done in the - Domainname and Category arguments, but it's better than to have a - warning at every invocation in a format string position. */ + Do this with inline functions when possible. */ /* These warnings would not occur with enabled NLS. */ /* A test case: ================================ foo.c ================================ #include #include "gettext.h" + extern const char *some_computed_string (void); + void foo (int n) { + textdomain ("pkg"); + bindtextdomain ("pkg", "/usr/share/locale"); + bind_textdomain_codeset ("pkg", "UTF-8"); + printf (gettext ("foo %d"), n); printf (dgettext ("toto", "foo %d"), n); printf (dcgettext ("toto", "foo %d", LC_MESSAGES), n); printf (ngettext ("foo %d", "bar %d", n), n); printf (dngettext ("toto", "foo %d", "bar %d", n), n); printf (dcngettext ("toto", "foo %d", "bar %d", n, LC_MESSAGES), n); + + printf ("%s", gettext ("between 7% & 19%.")); + printf ("%s", dgettext ("toto", "between 7% & 19%.")); + printf ("%s", dcgettext ("toto", "between 7% & 19%.", LC_MESSAGES)); + + printf (gettext (some_computed_string ())); + printf (dgettext ("toto", some_computed_string ())); + printf (dcgettext ("toto", some_computed_string (), LC_MESSAGES)); } ======================================================================= - $CC -Wformat=2 -S foo.c + $CC -Wall -Wformat=2 -S foo.c + $CC -Wall -Wformat=2 -S -x c++ foo.c */ -# if defined __GNUC__ && !defined __clang__ && !defined __cplusplus +# if (defined __GNUC__ || defined __clang__) && !defined __cplusplus +# if __GNUC__ + (__GNUC_MINOR__ >= 2) > 4 || defined __clang__ +# define _LIBGETTEXT_INLINE __always_inline__, __gnu_inline__ +# else +# define _LIBGETTEXT_INLINE __always_inline__ +# endif /* The return type 'const char *' serves the purpose of producing warnings for invalid uses of the value returned from these functions. */ -# if __GNUC__ >= 9 +# if defined __GNUC__ && __GNUC__ >= 9 && !defined __clang__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" # endif -# if __GNUC__ + (__GNUC_MINOR__ >= 2) > 4 -__attribute__ ((__always_inline__, __gnu_inline__)) -# else -__attribute__ ((__always_inline__)) -# endif +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (1))) extern inline # if !defined(__sun) const @@ -112,13 +126,13 @@ const char * gettext (const char *msgid) { - return msgid; -} -# if __GNUC__ + (__GNUC_MINOR__ >= 2) > 4 -__attribute__ ((__always_inline__, __gnu_inline__)) -# else -__attribute__ ((__always_inline__)) + return +# ifdef __sun + (char *) # endif + msgid; +} +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (2))) extern inline # if !defined(__sun) const @@ -127,13 +141,13 @@ char * dgettext (const char *domain, const char *msgid) { (void) domain; - return msgid; -} -# if __GNUC__ + (__GNUC_MINOR__ >= 2) > 4 -__attribute__ ((__always_inline__, __gnu_inline__)) -# else -__attribute__ ((__always_inline__)) + return +# ifdef __sun + (char *) # endif + msgid; +} +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (2))) extern inline # if !defined(__sun) const @@ -143,85 +157,178 @@ dcgettext (const char *domain, const char *msgid, int category) { (void) domain; (void) category; - return msgid; + return +# ifdef __sun + (char *) +# endif + msgid; } -# if __GNUC__ >= 9 +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (1), __format_arg__ (2))) +extern inline +# if !defined(__sun) +const +# endif +char * +ngettext (const char *msgid1, const char *msgid2, unsigned long n) +{ + return +# ifdef __sun + (char *) +# endif + (n == 1 ? msgid1 : msgid2); +} +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (2), __format_arg__ (3))) +extern inline +# if !defined(__sun) +const +# endif +char * +dngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long n) +{ + (void) domain; + return +# ifdef __sun + (char *) +# endif + (n == 1 ? msgid1 : msgid2); +} +__attribute__ ((_LIBGETTEXT_INLINE, __format_arg__ (2), __format_arg__ (3))) +extern inline +# if !defined(__sun) +const +# endif +char * +dcngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long n, int category) +{ + (void) domain; + (void) category; + return +# ifdef __sun + (char *) +# endif + (n == 1 ? msgid1 : msgid2); +} +__attribute__ ((_LIBGETTEXT_INLINE)) +extern inline +# if !defined(__sun) +const +# endif +char * +textdomain (const char *domainname) +{ + return +# ifdef __sun + (char *) +# endif + domainname; +} +# if defined __GNUC__ && __GNUC__ >= 9 && !defined __clang__ # pragma GCC diagnostic pop # endif -# elif defined __clang__ + +# elif (defined __GNUC__ || defined __clang__) && defined __cplusplus + +__attribute__ ((__format_arg__ (1))) +static inline const char * +_libgettext_gettext (const char *msgid) +{ + return msgid; +} # undef gettext -# define gettext(Msgid) ((const char *) (Msgid)) +# define gettext _libgettext_gettext +__attribute__ ((__format_arg__ (2))) +static inline const char * +_libgettext_dgettext (const char *domain, const char *msgid) +{ + (void) domain; + return msgid; +} # undef dgettext -# define dgettext(Domainname, Msgid) gettext (Msgid) +# define dgettext _libgettext_dgettext +__attribute__ ((__format_arg__ (2))) +static inline const char * +_libgettext_dcgettext (const char *domain, const char *msgid, int category) +{ + (void) domain; + (void) category; + return msgid; +} # undef dcgettext -# define dcgettext(Domainname, Msgid, Category) dgettext (Domainname, Msgid) +# define dcgettext _libgettext_dcgettext +__attribute__ ((__format_arg__ (1), __format_arg__ (2))) +static inline const char * +_libgettext_ngettext (const char *msgid1, const char *msgid2, unsigned long n) +{ + return (n == 1 ? msgid1 : msgid2); +} +# undef ngettext +# define ngettext _libgettext_ngettext +__attribute__ ((__format_arg__ (2), __format_arg__ (3))) +static inline const char * +_libgettext_dngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long n) +{ + (void) domain; + return (n == 1 ? msgid1 : msgid2); +} +# undef dngettext +# define dngettext _libgettext_dngettext +__attribute__ ((__format_arg__ (2), __format_arg__ (3))) +static inline const char * +_libgettext_dcngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long n, int category) +{ + (void) domain; + (void) category; + return (n == 1 ? msgid1 : msgid2); +} +# undef dcngettext +# define dcngettext _libgettext_dcngettext +static inline const char * +_libgettext_textdomain (const char *domainname) +{ + return domainname; +} +# undef textdomain +# define textdomain _libgettext_textdomain + # else -/* The conversions to 'const char *' via compound literals serve the purpose - of producing warnings for invalid uses of the value returned from these - functions and for invalid-typed Msgid arguments. */ + # undef gettext -# define gettext(Msgid) ((const char *) {(Msgid)}) -/* The conversions via compound literals serve the purpose of producing warnings - for invalid-typed arguments. */ +# define gettext(Msgid) _LIBGETTEXT_FUNCAST (const char *, Msgid) # undef dgettext # define dgettext(Domainname, Msgid) \ - ((void) (const char *) {(Domainname)}, gettext (Msgid)) + ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), gettext (Msgid)) # undef dcgettext # define dcgettext(Domainname, Msgid, Category) \ - ((void) (int) {(Category)}, dgettext (Domainname, Msgid)) -# endif - -# if (defined __GNUC__ && defined __cplusplus) || defined __clang__ -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ngettext (Msgid1, Msgid2, N) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - dngettext (Domainname, Msgid1, Msgid2, N) -# elif defined __GNUC__ && !defined __cplusplus -/* Silence -Wuseless-cast warnings. */ -# if __GNUC__ >= 14 -# pragma GCC diagnostic ignored "-Wuseless-cast" -# endif -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (const char *) (Domainname), ngettext (Msgid1, Msgid2, N)) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (int) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) -# else -/* The conversions to 'const char *' via compound literals serve the purpose - of producing warnings for invalid uses of the value returned from these - functions and for invalid-typed Msgid1 and Msgid2 arguments. */ + ((void) _LIBGETTEXT_FUNCAST (int, Category), \ + dgettext (Domainname, Msgid)) # undef ngettext # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 \ - ? ((void) (Msgid2), (const char *) {(Msgid1)}) \ - : ((void) (Msgid1), (const char *) {(Msgid2)})) -/* The conversions via compound literals serve the purpose of producing warnings - for invalid-typed arguments. */ + ? ((void) _LIBGETTEXT_FUNCAST (const char *, Msgid2), \ + _LIBGETTEXT_FUNCAST (const char *, Msgid1)) \ + : ((void) _LIBGETTEXT_FUNCAST (const char *, Msgid1), \ + _LIBGETTEXT_FUNCAST (const char *, Msgid2))) # undef dngettext # define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (const char *) {(Domainname)}, ngettext (Msgid1, Msgid2, N)) + ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \ + ngettext (Msgid1, Msgid2, N)) # undef dcngettext # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (int) {(Category)}, dngettext (Domainname, Msgid1, Msgid2, N)) + ((void) _LIBGETTEXT_FUNCAST (int, Category), \ + dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) _LIBGETTEXT_FUNCAST (const char *, Domainname) + # endif -# undef textdomain -# define textdomain(Domainname) ((const char *) {(Domainname)}) # undef bindtextdomain # define bindtextdomain(Domainname, Dirname) \ - ((void) (const char *) {(Domainname)}, (const char *) {(Dirname)}) + ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \ + _LIBGETTEXT_FUNCAST (const char *, Dirname)) # undef bind_textdomain_codeset # define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (const char *) {(Domainname)}, (const char *) {(Codeset)}) + ((void) _LIBGETTEXT_FUNCAST (const char *, Domainname), \ + _LIBGETTEXT_FUNCAST (const char *, Codeset)) #endif diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index b21d470cd0b..8e9a797f2c5 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -2004,7 +2004,7 @@ ifeq (,$(OMIT_GNULIB_MODULE_eloop-threshold)) ifneq (,$(gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION)) endif -EXTRA_DIST += eloop-threshold.h +EXTRA_DIST += min-eloop-threshold.h endif ## end gnulib module eloop-threshold diff --git a/lib/memrchr.c b/lib/memrchr.c index a7683c9aea1..b859288d689 100644 --- a/lib/memrchr.c +++ b/lib/memrchr.c @@ -50,7 +50,7 @@ __memrchr (void const *s, int c_in, size_t n) performance. On 64-bit hardware, unsigned long is generally 64 bits already. Change this typedef to experiment with performance. */ - typedef unsigned long int longword; + typedef unsigned long int longword _GL_ATTRIBUTE_MAY_ALIAS; unsigned reg_char c = (unsigned char) c_in; diff --git a/lib/min-eloop-threshold.h b/lib/min-eloop-threshold.h new file mode 100644 index 00000000000..26b0795a64b --- /dev/null +++ b/lib/min-eloop-threshold.h @@ -0,0 +1,42 @@ +/* Minimum threshold at which to diagnose ELOOP. Generic version. + Copyright (C) 2012-2026 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _MIN_ELOOP_THRESHOLD_H +#define _MIN_ELOOP_THRESHOLD_H 1 + +/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic + links that can be reliably traversed in the resolution of a + pathname in the absence of a loop." This makes it a minimum that + we should certainly accept. But it leaves open the possibility + that more might sometimes work--just not "reliably". + + For example, Linux implements a complex policy whereby there is a + small limit on the number of direct symlink traversals (a symlink + to a symlink to a symlink), but larger limit on the total number of + symlink traversals overall. Hence the SYMLOOP_MAX number should be + the small one, but the limit library functions enforce on users + should be the larger one. + + This constant should be large enough that it never rules out a file + name and directory tree that the underlying system (i.e. calls to 'open' + et al) would resolve successfully. It should be small enough that + actual loops are detected without a huge number of iterations. */ + +#define MIN_ELOOP_THRESHOLD 40 + +#endif diff --git a/lib/nproc.c b/lib/nproc.c index ef86975fb1f..821a913c3ab 100644 --- a/lib/nproc.c +++ b/lib/nproc.c @@ -437,12 +437,14 @@ get_cgroup2_cpu_quota (void) is not enabled for that part of the hierarchy. */ char cpu_max_file[PATH_MAX]; - snprintf (cpu_max_file, sizeof (cpu_max_file), - "%s%s/cpu.max", mount, cgroup); + int n = snprintf (cpu_max_file, sizeof (cpu_max_file), + "%s%s/cpu.max", mount, cgroup); - if ((fp = fopen (cpu_max_file, "r")) - && getline ("a_str, "a_size, fp) != -1 - && strncmp (quota_str, "max", 3) != 0) + if (n < 0 || sizeof cpu_max_file <= n) + fp = NULL; + else if ((fp = fopen (cpu_max_file, "r")) + && getline ("a_str, "a_size, fp) != -1 + && strncmp (quota_str, "max", 3) != 0) { long quota, period; if (sscanf (quota_str, "%ld %ld", "a, &period) == 2 && period) diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c index 9714698fcce..764d63339eb 100644 --- a/lib/rawmemchr.c +++ b/lib/rawmemchr.c @@ -25,6 +25,10 @@ # include # include +# ifndef __has_feature +# define __has_feature(a) 0 +# endif + /* Find the first occurrence of C in S. */ void * @@ -41,13 +45,21 @@ rawmemchr (const void *s, int c_in) - __builtin_cheri_offset_get (s))); # else + unsigned char c = c_in; + + /* Examine the memory an aligned longword at a time, when possible. + Doing so can go past the end of a lesser-aligned object, + which is harmless on most platforms but violates the rules of C, + so suppress this optimization on platforms where it is known to be + dangerous, namely, those using address sanitization. */ + +# if ! (defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)) + /* You can change this typedef to experiment with performance. */ - typedef uintptr_t longword; + typedef uintptr_t longword _GL_ATTRIBUTE_MAY_ALIAS; /* Verify that the longword type lacks padding bits. */ static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (uintptr_t)); - unsigned char c = c_in; - { const unsigned char *char_ptr; @@ -123,12 +135,6 @@ rawmemchr (const void *s, int c_in) longword_ptr++; } - s = longword_ptr; - } - - { - const unsigned char *char_ptr = s; - /* At this point, we know that one of the sizeof (longword) bytes starting at char_ptr is == c. If we knew endianness, we could determine the first such byte without any further memory @@ -136,6 +142,12 @@ rawmemchr (const void *s, int c_in) iteration. However, the following simple and portable code does not attempt this potential optimization. */ + s = longword_ptr; + } +# endif + + { + const unsigned char *char_ptr = s; while (*char_ptr != c) char_ptr++; return (void *) char_ptr; diff --git a/lib/readutmp.h b/lib/readutmp.h index badbbc4331e..31a27c1dda2 100644 --- a/lib/readutmp.h +++ b/lib/readutmp.h @@ -246,7 +246,7 @@ struct utmpx32 #endif /* Definition of WTMP_FILE. - On glibc systems, UTMP_FILE is "/var/log/wtmp". */ + On glibc systems, WTMP_FILE is "/var/log/wtmp". */ #if !defined WTMP_FILE && defined _PATH_WTMP # define WTMP_FILE _PATH_WTMP #endif @@ -258,6 +258,12 @@ struct utmpx32 # define WTMP_FILE "/etc/wtmp" #endif +/* Definition of WTMPDB_FILE. + On Debian and Devuan systems, WTMPDB_FILE is "/var/log/wtmp.db". */ +#ifndef WTMPDB_FILE +# define WTMPDB_FILE "/var/log/wtmp.db" +#endif + /* In early versions of Android, did not define BOOT_TIME or LOGIN_PROCESS, only USER_PROCESS. We need to use the value that is defined in newer versions of Android. */ diff --git a/lib/realloc.c b/lib/realloc.c index 9b35c23510c..0b42582c64a 100644 --- a/lib/realloc.c +++ b/lib/realloc.c @@ -28,10 +28,6 @@ #include #include -#ifdef __CHERI_PURE_CAPABILITY__ -# include -#endif - #ifndef _GL_INLINE_RPL_REALLOC /* Change the size of an allocated block of memory P to N bytes, @@ -99,11 +95,6 @@ rpl_realloc (void *p, size_t n) errno = ENOMEM; # endif -# ifdef __CHERI_PURE_CAPABILITY__ - if (result != NULL) - result = cheri_bounds_set (result, n); -# endif - return result; } diff --git a/lib/regex_internal.c b/lib/regex_internal.c index e5e5be84bd4..67deb812f7a 100644 --- a/lib/regex_internal.c +++ b/lib/regex_internal.c @@ -465,8 +465,8 @@ build_wcs_upper_buffer (re_string_t *pstr) pstr->offsets[byte_idx] = src_idx; ++src_idx; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; + /* And also convert it to wide char. */ + pstr->wcs[byte_idx++] = ch; if (__glibc_unlikely (mbclen == (size_t) -1)) pstr->cur_state = prev_st; } diff --git a/lib/strftime.c b/lib/strftime.c index 5a3544674e2..fbde375bfee 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -1641,11 +1641,18 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) subwidth = -1; subformat_width: { + /* Restrict flag propagation to %F and %Y so that we get glibc + consistent behavior for %D with glibc specific '_' and '-' flags. + Note the year is at the start of %F so OK to propagate there. */ + enum pad_style subpad = + (format_char == L_('F') || format_char == L_('Y') + ? pad : yr_spec); + retval_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1) subfmt, tp, CAL_ARGS (cal, caldate) - to_uppcase, pad, subwidth, + to_uppcase, subpad, subwidth, tzset_called extra_args LOCALE_ARG); if (FAILURE < 0 && len < 0) @@ -1654,7 +1661,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) STRFTIME_ARG (maxsize - i) subfmt, tp, CAL_ARGS (cal, caldate) - to_uppcase, pad, subwidth, + to_uppcase, subpad, subwidth, tzset_called extra_args LOCALE_ARG)); } diff --git a/lib/string.in.h b/lib/string.in.h index eb22a912c34..d05d983cd3d 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -312,7 +312,8 @@ _GL_EXTERN_C void *memset_explicit (void *__s, int __c, size_t __n) #if @GNULIB_EXPLICIT_BZERO@ # if ! @HAVE_EXPLICIT_BZERO@ _GL_FUNCDECL_SYS (explicit_bzero, void, - (void *__dest, size_t __n), _GL_ARG_NONNULL ((1))); + (void *__dest, size_t __n), + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2)); # endif _GL_CXXALIAS_SYS (explicit_bzero, void, (void *__dest, size_t __n)); _GL_CXXALIASWARN (explicit_bzero); @@ -482,7 +483,8 @@ _GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " _GL_FUNCDECL_RPL (mempcpy, void *, (void *restrict __dest, void const *restrict __src, size_t __n), - _GL_ARG_NONNULL ((1, 2))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3)); _GL_CXXALIAS_RPL (mempcpy, void *, (void *restrict __dest, void const *restrict __src, size_t __n)); @@ -491,7 +493,8 @@ _GL_CXXALIAS_RPL (mempcpy, void *, _GL_FUNCDECL_SYS (mempcpy, void *, (void *restrict __dest, void const *restrict __src, size_t __n), - _GL_ARG_NONNULL ((1, 2))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3)); # endif _GL_CXXALIAS_SYS (mempcpy, void *, (void *restrict __dest, void const *restrict __src, @@ -645,7 +648,8 @@ _GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " _GL_FUNCDECL_RPL (stpncpy, char *, (char *restrict __dst, char const *restrict __src, size_t __n), - _GL_ARG_NONNULL ((1, 2))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3)); _GL_CXXALIAS_RPL (stpncpy, char *, (char *restrict __dst, char const *restrict __src, size_t __n)); @@ -654,7 +658,8 @@ _GL_CXXALIAS_RPL (stpncpy, char *, _GL_FUNCDECL_SYS (stpncpy, char *, (char *restrict __dst, char const *restrict __src, size_t __n), - _GL_ARG_NONNULL ((1, 2))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3)); # endif _GL_CXXALIAS_SYS (stpncpy, char *, (char *restrict __dst, char const *restrict __src, @@ -861,7 +866,8 @@ _GL_WARN_ON_USE (strncat, "strncat is unportable - " _GL_FUNCDECL_RPL (strncpy, char *, (char *restrict __dst, char const *restrict __src, size_t __n), - _GL_ARG_NONNULL ((1, 2))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3)); _GL_CXXALIAS_RPL (strncpy, char *, (char *restrict __dst, char const *restrict __src, size_t __n)); @@ -946,13 +952,13 @@ _GL_WARN_ON_USE (strndup, "strndup is unportable - " # endif _GL_FUNCDECL_RPL (strnlen, size_t, (char const *__s, size_t __maxlen), _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2)); _GL_CXXALIAS_RPL (strnlen, size_t, (char const *__s, size_t __maxlen)); # else # if ! @HAVE_DECL_STRNLEN@ _GL_FUNCDECL_SYS (strnlen, size_t, (char const *__s, size_t __maxlen), _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2)); # endif _GL_CXXALIAS_SYS (strnlen, size_t, (char const *__s, size_t __maxlen)); # endif @@ -1352,7 +1358,7 @@ _GL_CXXALIASWARN (mbslen); at STRING and ending at STRING + LEN. */ _GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1)); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2); #endif #if @GNULIB_MBSCHR@ @@ -1460,7 +1466,8 @@ _GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) But beware that N is not a byte count but a character count! */ _GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) + _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); #endif #if @GNULIB_MBSPCASECMP@ diff --git a/lib/time.in.h b/lib/time.in.h index 5bbccf76627..2f470dd4cc9 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -45,9 +45,11 @@ # define _@GUARD_PREFIX@_TIME_H /* mingw's provides the functions asctime_r, ctime_r, gmtime_r, - localtime_r only if or has been included before. */ + localtime_r only if or has been included before + or if _POSIX_THREAD_SAFE_FUNCTIONS is defined. */ # if defined __MINGW32__ -# include +# undef _POSIX_THREAD_SAFE_FUNCTIONS +# define _POSIX_THREAD_SAFE_FUNCTIONS 200112L # endif # @INCLUDE_NEXT@ @NEXT_TIME_H@ diff --git a/lib/verify.h b/lib/verify.h index ad45c39d279..e15fad2e4fd 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -23,6 +23,8 @@ /* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC) works as per C11. This is supported by GCC 4.6.0+ and by clang 4+. + Check for __clang_major__ >= 5 instead of >= 4 because clang on Mac OS 10.7.5 + sets __clang_major__ to 4 even though it was derived from clang 3.2. Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as per C23. This is supported by GCC 9.1+. @@ -44,10 +46,22 @@ # endif #endif +/* in glibc may define _Static_assert with two arguments if the + compiler is in C89 or C99 mode. This matters especially with Clang: + (1) glibc < 2.34, before the commit c8ba52ab3350 ("misc: Sync cdefs.h + with gnulib"), doesn't check for __clang_major__ >= 4. + (2) The above condition for _GL_HAVE__STATIC_ASSERT checks for + __clang_major__ >= 5, so it's not in sync with glibc. */ +#if defined __GLIBC__ \ + && !defined __cplusplus && __STDC_VERSION__ < 201112 +# undef _Static_assert +#endif + /* FreeBSD 9.1 , included by and lots of other system headers, defines a conflicting _Static_assert that is no - better than ours; override it. */ -#ifndef _GL_HAVE__STATIC_ASSERT + better than ours; override it unless Gnulib's replacement + (included from config.h) already overrode it. */ +#if ! (defined _GL_HAVE__STATIC_ASSERT || defined _GL_STATIC_ASSERT) # include # undef _Static_assert #endif diff --git a/m4/getopt.m4 b/m4/getopt.m4 index c620b2b77f0..68fa60c95b2 100644 --- a/m4/getopt.m4 +++ b/m4/getopt.m4 @@ -1,5 +1,5 @@ # getopt.m4 -# serial 52 +# serial 53 dnl Copyright (C) 2002-2006, 2008-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -72,7 +72,8 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], AC_CHECK_HEADERS([getopt.h], [], [gl_replace_getopt=yes]) fi - dnl Test whether the function getopt_long is available. + dnl Test whether the functions getopt_long and getopt_long_only are both + dnl available. if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then AC_CHECK_FUNCS([getopt_long_only], [], [gl_replace_getopt=yes]) fi @@ -238,7 +239,8 @@ dnl is ambiguous with environment values that contain newlines. nocrash_init(); /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw, - and fails on Mac OS X 10.5, AIX 5.2, HP-UX 11, Solaris 10. */ + and fails on Mac OS X 10.5, NetBSD 10.0, AIX 5.2, HP-UX 11, + Solaris 10. */ { static char conftest[] = "conftest"; static char plus[] = "-+"; @@ -267,7 +269,8 @@ dnl is ambiguous with environment values that contain newlines. else if (optind != 2) result |= 8; } - /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0. */ + /* This code succeeds on glibc 2.8 + and fails on NetBSD 10.0, Cygwin 1.7.0. */ { static char program[] = "program"; static char foo[] = "foo"; @@ -279,7 +282,7 @@ dnl is ambiguous with environment values that contain newlines. else if (getopt (3, argv, "-p") != 'p') result |= 16; } - /* This code fails on glibc 2.11. */ + /* This code fails on glibc 2.11, NetBSD 10.0. */ { static char program[] = "program"; static char b[] = "-b"; diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index 12b0836e2a0..d8a6c9b114e 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -296,11 +296,9 @@ AC_DEFUN([gl_COMMON_BODY], [ we cannot omit the storage-class specifier. Therefore, the following rule applies: * The macros - _GL_ATTRIBUTE_CONST _GL_ATTRIBUTE_DEPRECATED _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_NODISCARD - _GL_ATTRIBUTE_PURE _GL_ATTRIBUTE_REPRODUCIBLE _GL_ATTRIBUTE_UNSEQUENCED which may expand to bracket syntax [[...]], must come first, before the diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index aec48742bbd..b42a37912aa 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -1344,7 +1344,6 @@ AC_DEFUN([gl_FILE_LIST], [ lib/dtotimespec.c lib/dup2.c lib/dynarray.h - lib/eloop-threshold.h lib/endian.c lib/endian.in.h lib/errno.in.h @@ -1430,6 +1429,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/mempcpy.c lib/memrchr.c lib/memset_explicit.c + lib/min-eloop-threshold.h lib/mini-gmp-gnulib.c lib/mini-gmp.c lib/mini-gmp.h diff --git a/m4/malloc.m4 b/m4/malloc.m4 index a95e33db86c..567b0e89d6a 100644 --- a/m4/malloc.m4 +++ b/m4/malloc.m4 @@ -1,5 +1,5 @@ # malloc.m4 -# serial 46 +# serial 47 dnl Copyright (C) 2007, 2009-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -104,6 +104,7 @@ AC_DEFUN([gl_FUNC_MALLOC_PTRDIFF], # Set gl_cv_func_malloc_gnu. AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF], [ + gl_MUSL_LIBC AC_CACHE_CHECK([whether malloc is ptrdiff_t safe], [gl_cv_malloc_ptrdiff], [AC_COMPILE_IFELSE( @@ -118,10 +119,30 @@ AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF], is no problem. */ #define NARROW_SIZE (SIZE_MAX <= PTRDIFF_MAX) - /* glibc 2.30 and later malloc refuses to exceed ptrdiff_t - bounds even on 32-bit platforms. We don't know which - non-glibc systems are safe. */ - #define KNOWN_SAFE (2 < __GLIBC__ + (30 <= __GLIBC_MINOR__)) + /* Whether address sanitization is in use. + clang 4 through 21 signal this only with __has_feature. */ + #if !defined __SANITIZE_ADDRESS__ && defined __has_feature + # if __has_feature (address_sanitizer) + # define __SANITIZE_ADDRESS__ 1 + # endif + #endif + + #if __OpenBSD__ || __NetBSD__ + #include + #endif + + /* Many platforms are safe: malloc stays in ptrdiff_t bounds. + However, with address sanitization, gcc (up to at least + gcc 16.1) and clang (up to at least clang 22) interpose + a malloc that can go over a 32-bit ptrdiff_t limit. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126436 + https://github.com/llvm/llvm-project/issues/212288 + If we don't know a platform is safe, assume it's unsafe. */ + #define KNOWN_SAFE \ + (((2 < __GLIBC__ + (30 <= __GLIBC_MINOR__)) || MUSL_LIBC \ + || 11 <= __FreeBSD__ || 800000000 <= __NetBSD_Version__ \ + || 201411 <= OpenBSD || defined _WIN32) \ + && !__SANITIZE_ADDRESS__) #if WIDE_PTRDIFF || NARROW_SIZE || KNOWN_SAFE return 0; diff --git a/m4/readutmp.m4 b/m4/readutmp.m4 index 3eeec0d0818..787fe4eaa15 100644 --- a/m4/readutmp.m4 +++ b/m4/readutmp.m4 @@ -1,5 +1,5 @@ # readutmp.m4 -# serial 32 +# serial 33 dnl Copyright (C) 2002-2026 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -9,11 +9,13 @@ dnl This file is offered as-is, without any warranty. AC_DEFUN([gl_READUTMP], [ AC_REQUIRE([gl_SYSTEMD_CHOICE]) + AC_REQUIRE([gl_WTMPDB_CHOICE]) - dnl Set READUTMP_LIB to '-lsystemd' or '', depending on whether use of - dnl systemd APIs is possible and desired (only the systemd login API, here). + dnl Set READUTMP_LIB to '-lsystemd' or '-lwtmpdb' or '', depending on whether + dnl use of systemd APIs is possible and desired (only the systemd login API, + dnl here) and whether use of wtmpdb APIs is possible and desired. dnl AC_LIB_LINKFLAGS_BODY would be overkill here, since few people install - dnl libsystemd in non-system directories. + dnl libsystemd or libwtmpdb in non-system directories. READUTMP_LIB= if test "$SYSTEMD_CHOICE" = yes; then AC_CHECK_HEADER([systemd/sd-login.h]) @@ -42,6 +44,14 @@ AC_DEFUN([gl_READUTMP], fi fi fi + if test "$WTMPDB_CHOICE" = yes; then + AC_CHECK_HEADER([wtmpdb.h]) + if test $ac_cv_header_wtmpdb_h = yes; then + AC_DEFINE([READUTMP_USE_WTMPDB], [1], + [Define if the readutmp module should use the wtmpdb API.]) + READUTMP_LIB=$READUTMP_LIB${READUTMP_LIB:+ }'-lwtmpdb' + fi + fi AC_SUBST([READUTMP_LIB]) gl_PREREQ_READUTMP_H diff --git a/src/image.c b/src/image.c index 531b597988e..f542bbe0cbe 100644 --- a/src/image.c +++ b/src/image.c @@ -453,7 +453,7 @@ ptrdiff_t image_bitmap_pixmap (struct frame *f, ptrdiff_t id) { /* HAVE_NTGUI needs the explicit cast here. */ - return (ptrdiff_t) FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; + return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; } #endif @@ -5566,7 +5566,7 @@ canvas_free_unused (void) static void canvas_apply_data (struct canvas *c, struct image_keyword *fmt) { - ptrdiff_t expected_size = (ptrdiff_t) c->width * c->height; + ptrdiff_t expected_size = (ptrdiff_t) {c->width} * c->height; Lisp_Object data = fmt[CANVAS_DATA].value; Lisp_Object file = fmt[CANVAS_FILE].value;