From patchwork Wed Dec 3 22:45:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Perkins X-Patchwork-Id: 4061 X-Patchwork-Delegate: vapier@gentoo.org Received: (qmail 11340 invoked by alias); 3 Dec 2014 22:46:43 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 11320 invoked by uid 89); 3 Dec 2014 22:46:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-ie0-f171.google.com X-Received: by 10.42.231.139 with SMTP id jq11mr4456623icb.84.1417646799511; Wed, 03 Dec 2014 14:46:39 -0800 (PST) From: James Perkins To: libc-alpha@sourceware.org Subject: [PATCH v3 2/4] [BZ #16141] strptime: fix %z minutes calculation Date: Wed, 3 Dec 2014 14:45:58 -0800 Message-Id: <1417646760-19563-2-git-send-email-james@loowit.net> In-Reply-To: <1417646760-19563-1-git-send-email-james@loowit.net> References: <1417646760-19563-1-git-send-email-james@loowit.net> This is part of a fix for [BZ #16141] strptime %z offset restriction. strptime supports a %z input field descriptor, which parses a time zone offset from UTC time into the broken-out time field tm_gmtoff. In the current implementation, the minutes portion calculation is correct only for minutes evenly divisible by 3. This is because the minutes value is converted to decimal time, but inadequate precision leads to rounding which calculates results that are too low for some values. For example, due to rounding, a +1159 offset string results in an incorrect tm_gmtoff of 43128 (== 11 * 3600 + 58.8 * 60) seconds, instead of 43140 (== 11 * 3600 + 59 * 60) seconds. In contrast, a +1157 offset (minutes divisible by 3) does not cause the bug, and results in a correct tm_gmtoff of 43020. When 'make check' is run on glibc, tst-strptime2 will report the error with the output: round 9: tm_gmtoff is 43056 round 10: tm_gmtoff is 43128 This fix calculates the offset from the hour and minute portions directly, without the rounding errors introduced by decimal time. The tst-strptime2 test succeeds with this patch applied. James 2014-12-03 James Perkins james@loowit.net [BZ #16141] * time/strptime_l.c (__strptime_internal): Fix %z minutes calculation, removing incorrect decimal time rounding, so that all minute values result in a valid seconds value. --- time/strptime_l.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/time/strptime_l.c b/time/strptime_l.c index b3a612e..be35f3b 100644 --- a/time/strptime_l.c +++ b/time/strptime_l.c @@ -770,16 +770,12 @@ __strptime_internal (rp, fmt, tmp, statep LOCALE_PARAM) else if (n != 4) /* Only two or four digits recognized. */ return NULL; - else - { - /* We have to convert the minutes into decimal. */ - if (val % 100 >= 60) - return NULL; - val = (val / 100) * 100 + ((val % 100) * 50) / 30; - } + else if (val % 100 >= 60) + /* Minutes valid range is 0 through 59. */ + return NULL; if (val > 1200) return NULL; - tm->tm_gmtoff = (val * 3600) / 100; + tm->tm_gmtoff = (val / 100) * 3600 + (val % 100) * 60; if (neg) tm->tm_gmtoff = -tm->tm_gmtoff; }