nstrftime: suggest to glibc how to avoid alloca
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 17 May 2023 17:27:40 +0000 (10:27 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 17 May 2023 19:04:35 +0000 (12:04 -0700)
* lib/nstrftime.c (widen) [COMPILE_WIDE]: Remove.
(__strftime_internal) [COMPILE_WIDE): Instead of converting the
multibyte time zone abbreviation into a potentially unbounded
alloca buffer, convert it directly into the output buffer.
Although this code is not used in Gnulib, this can help the glibc
developers avoid the problem on the glibc side.

ChangeLog
lib/nstrftime.c

index ecbc25ef064fd82b503a0631bcdfa7e3f09403c7..36b3c65b81b73310bd7000abab0b36e6914cd34e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2023-05-17  Paul Eggert  <eggert@cs.ucla.edu>
+
+       nstrftime: suggest to glibc how to avoid alloca
+       * lib/nstrftime.c (widen) [COMPILE_WIDE]: Remove.
+       (__strftime_internal) [COMPILE_WIDE): Instead of converting the
+       multibyte time zone abbreviation into a potentially unbounded
+       alloca buffer, convert it directly into the output buffer.
+       Although this code is not used in Gnulib, this can help the glibc
+       developers avoid the problem on the glibc side.
+
 2023-05-15  Bruno Haible  <bruno@clisp.org>
 
        doc: New chapter "Strings and Characters".
index 68bb560910d9f78fa27b74f8b5cc22d0666dedec..35a9307e1a749f4b11f37199e28fc9b6de80d1ac 100644 (file)
@@ -226,15 +226,6 @@ extern char *tzname[];
 #  undef __mbsrtowcs_l
 #  define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
 # endif
-# define widen(os, ws, l) \
-  {                                                                           \
-    mbstate_t __st;                                                           \
-    const char *__s = os;                                                     \
-    memset (&__st, '\0', sizeof (__st));                                      \
-    l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc);                            \
-    ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t));                     \
-    (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc);                           \
-  }
 #endif
 
 
@@ -1374,11 +1365,31 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
 #ifdef COMPILE_WIDE
           {
             /* The zone string is always given in multibyte form.  We have
-               to transform it first.  */
-            wchar_t *wczone;
-            size_t len;
-            widen (zone, wczone, len);
-            cpy (len, wczone);
+               to convert it to wide character.  */
+            size_t w = pad == L_('-') || width < 0 ? 0 : width;
+            char const *z = zone;
+            mbstate_t st = {0};
+            size_t len = __mbsrtowcs_l (p, &z, maxsize - i, &st, loc);
+            if (len == (size_t) -1)
+              return 0;
+            size_t incr = len < w ? w : len;
+            if (incr >= maxsize - i)
+              {
+                errno = ERANGE;
+                return 0;
+              }
+            if (p)
+              {
+                if (len < w)
+                  {
+                    size_t delta = w - len;
+                    wmemmove (p + delta, p, len);
+                    wchar_t wc = pad == L_('0') || pad == L_('+') ? L'0' : L' ';
+                    wmemset (p, wc, delta);
+                  }
+                p += incr;
+              }
+            i += incr;
           }
 #else
           cpy (strlen (zone), zone);