From owner-freebsd-bugs@FreeBSD.ORG Thu Dec 24 05:00:13 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3BF50106566B for ; Thu, 24 Dec 2009 05:00:13 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 080098FC18 for ; Thu, 24 Dec 2009 05:00:13 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id nBO50CcP001055 for ; Thu, 24 Dec 2009 05:00:12 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id nBO50CSl001050; Thu, 24 Dec 2009 05:00:12 GMT (envelope-from gnats) Resent-Date: Thu, 24 Dec 2009 05:00:12 GMT Resent-Message-Id: <200912240500.nBO50CSl001050@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Denis Chatelain Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D7AE21065696 for ; Thu, 24 Dec 2009 04:55:08 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id ACF688FC0C for ; Thu, 24 Dec 2009 04:55:08 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nBO4t8GQ083081 for ; Thu, 24 Dec 2009 04:55:08 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id nBO4t8TY083080; Thu, 24 Dec 2009 04:55:08 GMT (envelope-from nobody) Message-Id: <200912240455.nBO4t8TY083080@www.freebsd.org> Date: Thu, 24 Dec 2009 04:55:08 GMT From: Denis Chatelain To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/141939: strptime confuses July with June with the fr_FR locale X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Dec 2009 05:00:13 -0000 >Number: 141939 >Category: kern >Synopsis: strptime confuses July with June with the fr_FR locale >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Dec 24 05:00:12 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Denis Chatelain >Release: 7.2 >Organization: >Environment: FreeBSD (snip) 7.2-RELEASE-p4 FreeBSD 7.2-RELEASE-p4 #0: Fri Oct 2 08:22:32 UTC 2009 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 >Description: strptime has a bug with the fr_FR locale: when using the %B switch it will return June (juin) instead of July (juillet) when parsing it. Here's how it goes when parsing "juillet": (check all months until may, then June, "juin") - check for full month "juin" -> no match - check for abbreviated June month "jui" -> match; wrong, and it breaks without checking for juillet, effectively returning June. it returns NULL iff there pattern has something else after it (month year), silently misreading the month It does not seems to be fixed in later version (ie: 8.O) >How-To-Repeat: Feed "juillet" to this program, and you get the output "juin" instead of "juillet" (with no indication of failure): #include #include #include #include int main (int argc, char *argv[]) { char TheoricallyIdenticalDate[255]; char OriginalDate [255] ; char *result; struct tm timeptr; if (argc != 2) return 1; strlcpy (OriginalDate, argv[1], sizeof (OriginalDate)); setlocale (LC_TIME, "fr_FR.UTF-8"); memset (&timeptr, 0, sizeof (struct tm)); result = strptime (OriginalDate, "%B", &timeptr); if (result == 0) printf ("Failed parsing the date\n"); strftime (TheoricallyIdenticalDate, 255, "%B", &timeptr); printf ("before parsing: %s, after parsing: %s\n", OriginalDate, TheoricallyIdenticalDate); return 0; } >Fix: Check all full months first, then check abbreviations. That's my proposed patch. However, in the unpredictable world of languages, some could have month abbreviations longer than the full month names, so a more correct approach could to be to try to match the longest strings first, independently of the nature of the string (full or abbreviated). Patch attached with submission follows: --- /usr/src/lib/libc/stdtime/strptime.c 2009-04-15 05:14:26.000000000 +0200 +++ strptime.c 2009-12-24 05:34:10.000000000 +0100 @@ -408,6 +408,11 @@ if (strncasecmp(buf, tptr->month[i], len) == 0) break; + } + } + // Try the abbreviated month name if the full name wasn't found and Oalternative was not requested + if (i == asizeof(tptr->month) && !Oalternative) { + for (i = 0; i < asizeof(tptr->month); i++) { len = strlen(tptr->mon[i]); if (strncasecmp(buf, tptr->mon[i], len) == 0) >Release-Note: >Audit-Trail: >Unformatted: