From 453d903de916a9f705398152cec9db369b7d7bb8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 15 Nov 2025 01:05:05 -0800 Subject: [PATCH] Adjust to Gnulib strftime changes for macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop using the fprintftime module, as as with recent Gnulib changes it breaks the build on macOS, and fixing this would drag in threading libraries and macOS-specific libraries that are overkill for tar. Instead, just use strftime; that’s good enough here and arguably better in case someone attacks tar with a huge time format string. * gnulib.modules: Remove fprintftime. * src/checkpoint.c: Do not include fprintftime. (format_checkpoint_string): Always output some useful info (a decimal seconds count), even if localtime fails. Do not output more than 256 bytes of time info, as that’s likely a DoS attack. Stick with plain strftime, as fprintftime’s extra features are overkill here. --- gnulib.modules | 1 - src/checkpoint.c | 25 +++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/gnulib.modules b/gnulib.modules index 2640614d..ede48729 100644 --- a/gnulib.modules +++ b/gnulib.modules @@ -49,7 +49,6 @@ file-has-acl fileblocks flexmember fnmatch-gnu -fprintftime free-posix fseeko fstatat diff --git a/src/checkpoint.c b/src/checkpoint.c index 903b8ce3..a07a54ea 100644 --- a/src/checkpoint.c +++ b/src/checkpoint.c @@ -21,9 +21,7 @@ #include "common.h" #include - #include -#include #include #include @@ -153,6 +151,9 @@ checkpoint_finish_compile (void) } } +/* Get the number of columns in the FP output stream. + FIXME: The rest of the code counts bytes, not columns, + so columns don't line up if multi-byte characters are output. */ static intmax_t getwidth (FILE *fp) { @@ -304,11 +305,23 @@ format_checkpoint_string (FILE *fp, intmax_t len, case 't': { struct timespec ts = current_timespec (); - const char *fmt = arg ? arg : "%c"; struct tm *tm = localtime (&ts.tv_sec); - len = add_printf (len, - (tm ? fprintftime (fp, fmt, tm, 0, ts.tv_nsec) - : fprintf (fp, "????""-??""-?? ??:??:??"))); + char const *tmstr = NULL; + + /* Keep BUF relatively small, as any text timestamp + not fitting into BUF is likely a DoS attack. */ + char buf[max (SYSINT_BUFSIZE, 256)]; + + if (tm) + { + buf[0] = '\0'; + char const *fmt = arg ? arg : "%c"; + if (strftime (buf, sizeof buf, fmt, tm) != 0 || !buf[0]) + tmstr = buf; + } + if (!tmstr) + tmstr = timetostr (ts.tv_sec, buf); + len = add_printf (len, fprintf (fp, "%s", tmstr)); } break;