From: Bruno Haible Date: Thu, 30 Oct 2025 11:56:21 +0000 (+0100) Subject: fprintftime: Avoid size_t overflow for very large outputs. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec0649fa3af846da82d0cf9dbe4c89555c4e9033;p=thirdparty%2Fgnulib.git fprintftime: Avoid size_t overflow for very large outputs. Reported by Jeff Epler in . * lib/fprintftime.h: Include . (fprintftime): Change return type to off64_t. * lib/strftime.c (byte_count_t): New macro. (my_strftime, __strftime_internal): Change return type to off64_t. * modules/fprintftime (Depends-on): Add sys_types-h. * NEWS: Mention the change. --- diff --git a/ChangeLog b/ChangeLog index fb24efb175..b7f0310e00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2025-10-30 Bruno Haible + + fprintftime: Avoid size_t overflow for very large outputs. + Reported by Jeff Epler in + . + * lib/fprintftime.h: Include . + (fprintftime): Change return type to off64_t. + * lib/strftime.c (byte_count_t): New macro. + (my_strftime, __strftime_internal): Change return type to off64_t. + * modules/fprintftime (Depends-on): Add sys_types-h. + * NEWS: Mention the change. + 2025-10-29 Bruno Haible Fix support for Mac OS X/PowerPC. diff --git a/NEWS b/NEWS index de89ddb78c..55dfcd95b0 100644 --- a/NEWS +++ b/NEWS @@ -78,6 +78,8 @@ User visible incompatible changes Date Modules Changes +2025-10-30 fprintftime The return value is changed from size_t to off64_t. + 2025-08-05 git-merge-changelog This module is removed. Use the package from https://git.savannah.gnu.org/git/vc-changelog.git instead. diff --git a/lib/fprintftime.h b/lib/fprintftime.h index 9b868e8ae3..a340b86117 100644 --- a/lib/fprintftime.h +++ b/lib/fprintftime.h @@ -16,6 +16,7 @@ along with this program. If not, see . */ #include +#include #include #ifdef __cplusplus @@ -29,9 +30,11 @@ extern "C" { Output to stream FP the result of formatting (according to the nstrftime format string, FMT) the time data, *TM, and the ZONE - and NANOSECONDS values. */ -size_t fprintftime (FILE *fp, char const *fmt, struct tm const *tm, - timezone_t zone, int nanoseconds); + and NANOSECONDS values. + + Return the number of bytes written to the stream (always >= 0). */ +off64_t fprintftime (FILE *fp, char const *fmt, struct tm const *tm, + timezone_t zone, int nanoseconds); #ifdef __cplusplus diff --git a/lib/strftime.c b/lib/strftime.c index 27e2ca0976..3898a7873d 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -198,12 +198,17 @@ enum pad_style # define mktime(tp) __mktime64 (tp) #endif +/* For functions that fill an in-memory string, the number of bytes fits in a + size_t. For functions that write to a stream, the number of bytes fits in + an off64_t (a type that is always at least 64 bits large). */ #if FPRINTFTIME # define STREAM_OR_CHAR_T FILE # define STRFTIME_ARG(x) /* empty */ +# define byte_count_t off64_t #else # define STREAM_OR_CHAR_T CHAR_T # define STRFTIME_ARG(x) x, +# define byte_count_t size_t #endif #if FPRINTFTIME @@ -894,12 +899,13 @@ static CHAR_T const c_month_names[][sizeof "September"] = # define ns 0 #endif -static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t) - const CHAR_T *, const struct tm *, - CAL_ARGS (const struct calendar *, - struct calendar_date *) - bool, enum pad_style, int, bool * - extra_args_spec LOCALE_PARAM); +static byte_count_t __strftime_internal (STREAM_OR_CHAR_T *, + STRFTIME_ARG (size_t) + const CHAR_T *, const struct tm *, + CAL_ARGS (const struct calendar *, + struct calendar_date *) + bool, enum pad_style, int, bool * + extra_args_spec LOCALE_PARAM); #if !defined _LIBC \ && (!(HAVE_ONLY_C_LOCALE || (USE_C_LOCALE && !HAVE_STRFTIME_L)) \ @@ -1107,7 +1113,7 @@ get_tm_zone (timezone_t tz, char *ubuf, int ubufsize, int modifier, characters written. If S is NULL, nothing will be written anywhere, so to determine how many characters would be written, use NULL for S and (size_t) -1 for MAXSIZE. */ -size_t +byte_count_t my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const CHAR_T *format, const struct tm *tp extra_args_spec LOCALE_PARAM) @@ -1150,7 +1156,7 @@ libc_hidden_def (my_strftime) UPCASE indicates that the result should be converted to upper case. YR_SPEC and WIDTH specify the padding and width for the year. *TZSET_CALLED indicates whether tzset has been called here. */ -static size_t +static byte_count_t __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const CHAR_T *format, const struct tm *tp, @@ -1221,7 +1227,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) # define ap_len 2 #endif - size_t i = 0; + byte_count_t i = 0; STREAM_OR_CHAR_T *p = s; const CHAR_T *f; #if DO_MULTIBYTE && !defined COMPILE_WIDE diff --git a/modules/fprintftime b/modules/fprintftime index 2eacd8526f..121073af1f 100644 --- a/modules/fprintftime +++ b/modules/fprintftime @@ -8,6 +8,7 @@ lib/strftime.c Depends-on: stdio-h +sys_types-h nstrftime time_rz