tzdata/backport-strftime-conform-better-to-POSIX.patch
2020-10-10 19:03:29 +08:00

134 lines
3.7 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 8b238ec54c09556eb2aa405c1741eedfd12c4a87 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 8 Aug 2020 12:19:28 -0700
Subject: [PATCH 24/47] strftime: conform better to POSIX+
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The latest POSIX draft specifies errno values for some strftime
errors. Implement those, plus one other one: a reliable way
to determine whether 0 represents failure or buffer exhaustion
(Ill propose this to POSIX).
* newstrftime.3 (RETURN VALUE): Document this.
* strftime.c (strftime): Set errno according to current draft of
POSIX. Also, set errno to ERANGE on overflow, and preserve errno
if there is no error.
(_fmt): Return NULL if %s would be out of range. Callers changed.
---
newstrftime.3 | 34 +++++++++++++++++++++++++++-------
strftime.c | 24 +++++++++++++++++++++++-
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/newstrftime.3 b/newstrftime.3
index 63842c7..887aba5 100644
--- a/newstrftime.3
+++ b/newstrftime.3
@@ -82,13 +82,6 @@ and one other character.
No more than
.I maxsize
bytes are placed into the array.
-If the total number of resulting bytes, including the terminating
-NUL character, is not more than
-.IR maxsize ,
-.B strftime
-returns the number of bytes placed into the array, not counting the
-terminating NUL.
-Otherwise, zero is returned and the array contents are unspecified.
.PP
Each conversion specification is replaced by the characters as
follows which are then copied into the array.
@@ -259,6 +252,33 @@ is replaced by a single %.
is replaced by the locale's date and time in
.BR date (1)
format.
+.SH "RETURN VALUE"
+If the conversion is successful,
+.B strftime
+returns the number of bytes placed into the array, not counting the
+terminating NUL;
+.B errno
+is unchanged if the returned value is zero.
+Otherwise,
+.B errno
+is set to indicate the error, zero is returned,
+and the array contents are unspecified.
+.SH ERRORS
+This function fails if:
+.TP
+[ERANGE]
+The total number of resulting bytes, including the terminating
+NUL character, is more than
+.IR maxsize .
+.PP
+This function may fail if:
+.TP
+[EOVERFLOW]
+The format includes an
+.c %s
+conversion and the number of seconds since the Epoch cannot be represented
+in a
+.c time_t .
.SH SEE ALSO
date(1),
getenv(3),
diff --git a/strftime.c b/strftime.c
index 14cbc9a..4f871cd 100644
--- a/strftime.c
+++ b/strftime.c
@@ -130,10 +130,15 @@ size_t
strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
{
char * p;
+ int saved_errno = errno;
enum warn warn = IN_NONE;
tzset();
p = _fmt(format, t, s, s + maxsize, &warn);
+ if (!p) {
+ errno = EOVERFLOW;
+ return 0;
+ }
if (DEPRECATE_TWO_DIGIT_YEARS
&& warn != IN_NONE && getenv(YEAR_2000_NAME)) {
fprintf(stderr, "\n");
@@ -146,9 +151,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
else fprintf(stderr, "all locales");
fprintf(stderr, "\n");
}
- if (p == s + maxsize)
+ if (p == s + maxsize) {
+ errno = ERANGE;
return 0;
+ }
*p = '\0';
+ errno = saved_errno;
return p - s;
}
@@ -312,7 +320,21 @@ label:
time_t mkt;
tm = *t;
+ tm.tm_yday = -1;
mkt = mktime(&tm);
+ if (mkt == (time_t) -1) {
+ /* Fail unless this -1 represents
+ a valid time. */
+ struct tm tm_1;
+ if (!localtime_r(&mkt, &tm_1))
+ return NULL;
+ if (!(tm.tm_year == tm_1.tm_year
+ && tm.tm_yday == tm_1.tm_yday
+ && tm.tm_hour == tm_1.tm_hour
+ && tm.tm_min == tm_1.tm_min
+ && tm.tm_sec == tm_1.tm_sec))
+ return NULL;
+ }
if (TYPE_SIGNED(time_t))
sprintf(buf, "%"PRIdMAX,
(intmax_t) mkt);
--
1.8.3.1