mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: musl@lists.openwall.com
Subject: Re: Bugs in strftime
Date: Tue, 6 Feb 2018 12:46:18 -0500	[thread overview]
Message-ID: <20180206174618.GB1220@brightrain.aerifal.cx> (raw)
In-Reply-To: <20180205175124.GZ1627@brightrain.aerifal.cx>

[-- Attachment #1: Type: text/plain, Size: 614 bytes --]

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

[-- Attachment #2: 0001-fix-strftime-field-widths-with-F-format-and-zero-yea.patch --]
[-- Type: text/plain, Size: 1250 bytes --]

From 596207aa38b0db33f222c9924a1310fee3de88b5 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
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


[-- Attachment #3: 0002-adjust-strftime-modifier-to-match-apparent-intent-of.patch --]
[-- Type: text/plain, Size: 2043 bytes --]

From c7f0da4134d4e7f2efd295e7fb738c65c469fbd1 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
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


  parent reply	other threads:[~2018-02-06 17:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-02 17:07 Dennis Wölfing
2018-02-05 17:51 ` Rich Felker
2018-02-06 16:10   ` Dennis Wölfing
2018-02-06 17:30     ` Rich Felker
2018-02-06 17:46   ` Rich Felker [this message]
2018-02-06 20:24     ` Dennis Wölfing
2018-02-07 20:35       ` Szabolcs Nagy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180206174618.GB1220@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).