summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2023-05-17 10:27:40 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2023-05-17 12:04:35 -0700
commit0a4e0cab0dbb2a70e26484e32378784b5106ae08 (patch)
tree4e9a5f08b9250ba4fb23625803cc63b5862e6426
parent8c4d0fbf4c45df8e86acbb338b154930c5498dc3 (diff)
downloadgnulib-0a4e0cab0dbb2a70e26484e32378784b5106ae08.tar.gz
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.
-rw-r--r--ChangeLog10
-rw-r--r--lib/nstrftime.c39
2 files changed, 35 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index ecbc25ef06..36b3c65b81 100644
--- 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".
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index 68bb560910..35a9307e1a 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -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);