diff options
author | Karl Williamson <khw@cpan.org> | 2021-02-09 11:10:19 -0700 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2021-02-17 17:57:49 -0800 |
commit | 1c97b6b159e3433bbeeb964c3f357cc57158cbb8 (patch) | |
tree | d9c6f4ecf9d8b18ebe4006c52af9beb55437fb3c /util.c | |
parent | 440416fb0ae381ccfc5c98c0194915188dd1cc5a (diff) | |
download | perl-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.c | 31 |
1 files changed, 22 insertions, 9 deletions
@@ -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; |