From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/12468 Path: news.gmane.org!.POSTED!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: Bugs in strftime Date: Tue, 6 Feb 2018 12:46:18 -0500 Message-ID: <20180206174618.GB1220@brightrain.aerifal.cx> References: <52570ac7-4ba2-0c7a-04b8-c1c9727a5509@gmx.de> <20180205175124.GZ1627@brightrain.aerifal.cx> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="jI8keyz6grp/JLjh" Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1517939086 14450 195.159.176.226 (6 Feb 2018 17:44:46 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 6 Feb 2018 17:44:46 +0000 (UTC) User-Agent: Mutt/1.5.21 (2010-09-15) To: musl@lists.openwall.com Original-X-From: musl-return-12484-gllmg-musl=m.gmane.org@lists.openwall.com Tue Feb 06 18:44:42 2018 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1ej7IC-0002lR-Kz for gllmg-musl@m.gmane.org; Tue, 06 Feb 2018 18:44:28 +0100 Original-Received: (qmail 1462 invoked by uid 550); 6 Feb 2018 17:46:31 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 1425 invoked from network); 6 Feb 2018 17:46:30 -0000 Content-Disposition: inline In-Reply-To: <20180205175124.GZ1627@brightrain.aerifal.cx> Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:12468 Archived-At: --jI8keyz6grp/JLjh Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Feb 05, 2018 at 12:51:24PM -0500, Rich Felker wrote: > > This bug is causing these failures: > > > "%+3C": expected "+20", got "020" > > > "%+11F": expected "+2016-01-03", got "02016-01-03" > > > "%+5G": expected "+2015", got "02015" > > > "%+5Y": expected "+2016", got "02016" > > > "%+5Y": expected "+0000", got "00000" > > I'll need to look over how to change the logic to match the desired > behavior but it shouldn't be hard. Attaching a patch I intend to push if I don't find any problems, and the one I've already got queued up for the %F issue. Let me know if you see any issues with them. Rich --jI8keyz6grp/JLjh Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-fix-strftime-field-widths-with-F-format-and-zero-yea.patch" Content-Transfer-Encoding: 8bit >From 596207aa38b0db33f222c9924a1310fee3de88b5 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 5 Feb 2018 13:36:04 -0500 Subject: [PATCH 1/2] fix strftime field widths with %F format and zero year MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the code to strip initial sign and leading zeros inadvertently stripped all the zeros and the subsequent '-' separating the month. instead, only strip sign characters from the very first position, and only strip zeros when they are followed by another digit. based on testing by Dennis Wölfing. --- src/time/strftime.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/time/strftime.c b/src/time/strftime.c index d1ca7ca..16b3bb2 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -251,7 +251,8 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st t = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad); if (!t) break; if (width) { - for (; *t=='+' || *t=='-' || (*t=='0'&&t[1]); t++, k--); + if (*t=='+' || *t=='-') t++, k--; + for (; *t=='0' && t[1]-'0'<10U; t++, k--); width--; if (plus && tm->tm_year >= 10000-1900) s[l++] = '+'; -- 2.10.0 --jI8keyz6grp/JLjh Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0002-adjust-strftime-modifier-to-match-apparent-intent-of.patch" Content-Transfer-Encoding: 8bit >From c7f0da4134d4e7f2efd295e7fb738c65c469fbd1 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 6 Feb 2018 12:31:06 -0500 Subject: [PATCH 2/2] adjust strftime + modifier to match apparent intent of POSIX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it's unclear from the specification whether the word "consumes" in "consumes more than four bytes to represent a year" refers just to significant places or includes leading zeros due to field width padding. however the examples in the rationale indicate that the latter was the intent. in particular, the year 270 is shown being formatted by %+5Y as +0270 rather than 00270. previously '+' prefixing was implemented just by comparing the year against 10000. instead, count the number of significant digits and padding bytes to be added, and use the total to determine whether to apply the '+' prefix. based on testing by Dennis Wölfing. --- src/time/strftime.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/time/strftime.c b/src/time/strftime.c index 16b3bb2..708875e 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -251,15 +251,21 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st t = __strftime_fmt_1(&buf, &k, *f, tm, loc, pad); if (!t) break; if (width) { + /* Trim off any sign and leading zeros, then + * count remaining digits to determine behavior + * for the + flag. */ if (*t=='+' || *t=='-') t++, k--; for (; *t=='0' && t[1]-'0'<10U; t++, k--); - width--; - if (plus && tm->tm_year >= 10000-1900) - s[l++] = '+'; - else if (tm->tm_year < -1900) + if (width < k) width = k; + size_t d; + for (d=0; t[d]-'0'<10U; d++); + if (tm->tm_year < -1900) { s[l++] = '-'; - else - width++; + width--; + } else if (plus && d+(width-k) >= (*p=='C'?3:5)) { + s[l++] = '+'; + width--; + } for (; width > k && l < n; width--) s[l++] = '0'; } -- 2.10.0 --jI8keyz6grp/JLjh--