That can be triggered with:
   ls -l --time-style='+%_10000z' /dev/null

* lib/strftime.c (do_number_sign_and_padding): Check buffer limits
before writing padding, which was inadvertently removed in
commit 1c740444 (Dec 2019).
* tests/test-nstrftime.h: Add a test case.
---
 lib/strftime.c         | 6 +++---
 tests/test-nstrftime.h | 9 +++++++++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/lib/strftime.c b/lib/strftime.c
index 25a300dd70..5915acad38 100644
--- a/lib/strftime.c
+++ b/lib/strftime.c
@@ -1936,13 +1936,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG 
(size_t maxsize)
               {
                 if (pad == SPACE_PAD)
                   {
-                    if (p)
-                      memset_space (p, padding);
-                    if (ckd_add (&i, i, padding) && FPRINTFTIME)
+                    if (incr_overflow (padding))
                       {
                         errno = ERANGE;
                         return FAILURE;
                       }
+                    if (p)
+                      memset_space (p, padding);
                     width -= padding;
                   }
                 width_add1 (0, sign_char);
diff --git a/tests/test-nstrftime.h b/tests/test-nstrftime.h
index 0b7cdb0da0..73096af17a 100644
--- a/tests/test-nstrftime.h
+++ b/tests/test-nstrftime.h
@@ -92,6 +92,15 @@ posixtm_test (void)
                   T[i].fmt, buf, T[i].exp);
           fflush (stdout);
         }
+
+      /* A one-byte buffer must fail without writing beyond its limit.
+         In particular, it is too small for the padding in %_10z.  */
+      memset (buf, '~', sizeof buf - 1);
+      buf[sizeof buf - 1] = '\0';
+      errno = 0;
+      ASSERT (FUNC (buf, 1, T[i].fmt, tm, NULL, T[i].in_ns) == -1);
+      ASSERT (errno == ERANGE);
+      ASSERT (strspn (buf + 1, "~") == sizeof buf - 2);
     }
 
   return fail;
-- 
2.56.0


Reply via email to