From: Paul Eggert Date: Sun, 23 Nov 2025 19:42:57 +0000 (-0800) Subject: du,ls: don’t modify getenv strings X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2199c9003eafab7bab0f670d70e2869721e4813f;p=thirdparty%2Fcoreutils.git du,ls: don’t modify getenv strings Fix du and ls to conform to the POSIX getenv spec, which says you can’t modify strings returned by getenv unless you put the string there directly, or used putenv. This portability bug was found by strict C23 checking using qualifier-generic functions. * bootstrap.conf (gnulib_modules): Add xmemdup0. Sort. * src/du.c (main): * src/ls.c (decode_switches): Don’t modify the string that getenv returns. Instead, use xmemdup0 if needed, and include xmemdup0.h. --- diff --git a/NEWS b/NEWS index acb3a4e187..ed33d27aa8 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,10 @@ GNU coreutils NEWS -*- outline -*- ** Bug fixes + du and ls no longer modify strings returned by getenv. + POSIX says this is not portable. + [bug introduced in fileutils-4.1.6] + md5sum --text correctly translates CRLF line endings with the MSYS2 runtime. This also applies to the sha*sum and b2sum utilities. [This bug was present in "the beginning".] @@ -16,6 +20,9 @@ GNU coreutils NEWS -*- outline -*- indicate the line count acceleration being used. [bug introduced in coreutils-9.0] + Programs now port to C23 platforms that strictly check types when + qualifier-generic functions like strchr are used. + ** New Features configure accepts a new --enable-single-binary=hardlinks mode to build the diff --git a/bootstrap.conf b/bootstrap.conf index ec68ac8bfe..356aaabef8 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -69,8 +69,8 @@ gnulib_modules=" crc-x86_64 crypto/md5 crypto/sha1 - crypto/sha3 crypto/sha256 + crypto/sha3 crypto/sha512 crypto/sm3 cycle-check @@ -215,14 +215,14 @@ gnulib_modules=" pipe2 posix-shell posix_spawn - posix_spawnattr_destroy - posix_spawnattr_init - posix_spawnattr_setflags - posix_spawnattr_setsigdefault posix_spawn_file_actions_addclose posix_spawn_file_actions_adddup2 posix_spawn_file_actions_destroy posix_spawn_file_actions_init + posix_spawnattr_destroy + posix_spawnattr_init + posix_spawnattr_setflags + posix_spawnattr_setsigdefault posix_spawnp posixtm posixver @@ -325,6 +325,7 @@ gnulib_modules=" xgetgroups xgethostname xmemcoll + xmemdup0 xnanosleep xprintf xprintf-posix diff --git a/src/du.c b/src/du.c index c6d6d7b334..105acb2dfd 100644 --- a/src/du.c +++ b/src/du.c @@ -40,6 +40,7 @@ #include "stat-time.h" #include "stdio--.h" #include "xfts.h" +#include "xmemdup0.h" #include "xstrtol.h" #include "xstrtol-error.h" @@ -962,9 +963,9 @@ main (int argc, char **argv) { /* Ignore anything after a newline, for compatibility with ls. */ - char *p = strchr (time_style, '\n'); + char const *p = strchr (time_style, '\n'); if (p) - *p = '\0'; + time_style = xmemdup0 (time_style, p - time_style); } else { diff --git a/src/ls.c b/src/ls.c index a81bab9c64..6b5f2b053f 100644 --- a/src/ls.c +++ b/src/ls.c @@ -70,20 +70,22 @@ #include +/* Gnulib includes. */ #include "acl.h" +#include "areadlink.h" #include "argmatch.h" -#include "system.h" #include "assure.h" +#include "c-ctype.h" #include "c-strcase.h" +#include "canonicalize.h" #include "dev-ino.h" +#include "filemode.h" #include "filenamecat.h" +#include "filevercmp.h" #include "hard-locale.h" #include "hash.h" #include "human.h" -#include "filemode.h" -#include "filevercmp.h" #include "idcache.h" -#include "ls.h" #include "mbswidth.h" #include "mpsort.h" #include "obstack.h" @@ -91,16 +93,18 @@ #include "stat-size.h" #include "stat-time.h" #include "strftime.h" -#include "term-sig.h" #include "xdectoint.h" -#include "xstrtol.h" +#include "xgethostname.h" +#include "xmemdup0.h" #include "xstrtol-error.h" -#include "areadlink.h" +#include "xstrtol.h" + +#include "system.h" + #include "dircolors.h" -#include "xgethostname.h" -#include "c-ctype.h" -#include "canonicalize.h" +#include "ls.h" #include "statx.h" +#include "term-sig.h" /* Include last to avoid a clash of include guards with some premature versions of libcap. @@ -1904,7 +1908,7 @@ stdout_isatty (void) static int decode_switches (int argc, char **argv) { - char const *time_style_option = nullptr; + char *time_style_option = nullptr; /* These variables are false or -1 unless a switch says otherwise. */ bool kibibytes_specified = false; @@ -2151,7 +2155,7 @@ decode_switches (int argc, char **argv) case FULL_TIME_OPTION: format_opt = long_format; - time_style_option = "full-iso"; + time_style_option = (char *) "full-iso"; break; case COLOR_OPTION: @@ -2377,35 +2381,39 @@ decode_switches (int argc, char **argv) if (format == long_format) { - char const *style = time_style_option; - static char const posix_prefix[] = "posix-"; - + char *envstyle = nullptr; + char *style = time_style_option; if (! style) - { - style = getenv ("TIME_STYLE"); - if (! style) - style = "locale"; - } + style = envstyle = getenv ("TIME_STYLE"); - while (STREQ_LEN (style, posix_prefix, sizeof posix_prefix - 1)) + if (! style) + style = (char *) "locale"; + else { - if (! hard_locale (LC_TIME)) - return optind; - style += sizeof posix_prefix - 1; + static char const posix_prefix[] = "posix-"; + while (STREQ_LEN (style, posix_prefix, sizeof posix_prefix - 1)) + { + if (! hard_locale (LC_TIME)) + return optind; + style += sizeof posix_prefix - 1; + } } if (*style == '+') { - char const *p0 = style + 1; + char *p0 = style + 1; char *p0nl = strchr (p0, '\n'); char const *p1 = p0; if (p0nl) { - if (strchr (p0nl + 1, '\n')) + p1 = p0nl + 1; + if (strchr (p1, '\n')) error (LS_FAILURE, 0, _("invalid time style format %s"), quote (p0)); - *p0nl++ = '\0'; - p1 = p0nl; + if (envstyle) + p0 = xmemdup0 (p0, p0nl - p0); + else + *p0nl = '\0'; } long_time_format[0] = p0; long_time_format[1] = p1;