summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2021-02-09 11:10:19 -0700
committerKarl Williamson <khw@cpan.org>2021-02-17 17:57:49 -0800
commit1c97b6b159e3433bbeeb964c3f357cc57158cbb8 (patch)
treed9c6f4ecf9d8b18ebe4006c52af9beb55437fb3c /util.c
parent440416fb0ae381ccfc5c98c0194915188dd1cc5a (diff)
downloadperl-1c97b6b159e3433bbeeb964c3f357cc57158cbb8.tar.gz
my_strftime(): Don't assume empty %p is an error
The strftime() format %p yields an am/pm indicator. Many locales don't have this distinction, and so a format containing just this specifier will return an empty string. Prior to this commit, that was considered an error. What was going on is we kept enlarging the buffer to find a non-empty return, to no avail, and so treat it as an error. This commit special cases this to not make it an error. (It's hard to imagine that the am/pm string alone would exceed the 200 byte limit.)
Diffstat (limited to 'util.c')
-rw-r--r--util.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/util.c b/util.c
index b28800d4ec..8103260181 100644
--- a/util.c
+++ b/util.c
@@ -4215,20 +4215,22 @@ giving localized results.
Newx(buf, buflen, char);
GCC_DIAG_IGNORE_STMT(-Wformat-nonliteral); /* fmt checked by caller */
+
len = strftime(buf, buflen, fmt, &mytm);
+
GCC_DIAG_RESTORE_STMT;
/*
- ** The following is needed to handle to the situation where
+ ** The following is needed to handle the situation where
** tmpbuf overflows. Basically we want to allocate a buffer
- ** and try repeatedly. The reason why it is so complicated
- ** is that getting a return value of 0 from strftime can indicate
- ** one of the following:
+ ** and try repeatedly, until it's large enough. The reason why it is so
+ ** complicated ** is that getting a return value of 0 from strftime can
+ ** indicate one of the following:
** 1. buffer overflowed,
** 2. illegal conversion specifier, or
- ** 3. the format string specifies nothing to be returned(not
- ** an error). This could be because format is an empty string
- ** or it specifies %p that yields an empty string in some locale.
+ ** 3. the format string specifies nothing to be returned (which isn't an
+ ** an error). This could be because the format is an empty string
+ ** or it specifies %p which yields an empty string in some locales.
** If there is a better way to make it portable, go ahead by
** all means.
*/
@@ -4250,8 +4252,19 @@ giving localized results.
break;
/* heuristic to prevent out-of-memory errors */
if (bufsize > 100*fmtlen) {
- Safefree(buf);
- buf = NULL;
+
+ /* "%p" can legally return nothing, assume that was the case if we
+ * can't make the buffer large enough to get a non-zero return. For
+ * any other formats, assume it is an error (probably it is an illegal
+ * conversion specifier.) */
+ if (strEQ(fmt, "%p")) {
+ Renew(buf, 1, char);
+ *buf = '\0';
+ }
+ else {
+ Safefree(buf);
+ buf = NULL;
+ }
break;
}
bufsize *= 2;