]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
fprintftime: Avoid size_t overflow for very large outputs.
authorBruno Haible <bruno@clisp.org>
Thu, 30 Oct 2025 11:56:21 +0000 (12:56 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 30 Oct 2025 11:56:21 +0000 (12:56 +0100)
Reported by Jeff Epler <jepler@unpythonic.net> in
<https://lists.gnu.org/archive/html/bug-gnulib/2025-10/msg00126.html>.

* lib/fprintftime.h: Include <sys/types.h>.
(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.

ChangeLog
NEWS
lib/fprintftime.h
lib/strftime.c
modules/fprintftime

index fb24efb175f0d13080f3a9ff0aa9ae5cbb233200..b7f0310e00751072450454efaff4f6b4dd67ea20 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2025-10-30  Bruno Haible  <bruno@clisp.org>
+
+       fprintftime: Avoid size_t overflow for very large outputs.
+       Reported by Jeff Epler <jepler@unpythonic.net> in
+       <https://lists.gnu.org/archive/html/bug-gnulib/2025-10/msg00126.html>.
+       * lib/fprintftime.h: Include <sys/types.h>.
+       (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  <bruno@clisp.org>
 
        Fix support for Mac OS X/PowerPC.
diff --git a/NEWS b/NEWS
index de89ddb78c6b6e9ef303c5ae736d8819c19fcec2..55dfcd95b0d4ee25a4d9b234993fb09055919f61 100644 (file)
--- 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.
index 9b868e8ae34634ac5e1375a8a1c9dce9669a4823..a340b86117e5e7dc78f36d667809255e565ccc6d 100644 (file)
@@ -16,6 +16,7 @@
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
 #include <stdio.h>
+#include <sys/types.h>
 #include <time.h>
 
 #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
index 27e2ca0976a973333fac42dcc8f11467967bfbf9..3898a7873d43a71dac56d85a0184fe64f59ded50 100644 (file)
@@ -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
index 2eacd8526f9f73e26d486f2e559d7374cadc66b5..121073af1f6c4f674d3b90c7df6c31029f887aac 100644 (file)
@@ -8,6 +8,7 @@ lib/strftime.c
 
 Depends-on:
 stdio-h
+sys_types-h
 nstrftime
 time_rz