From nobody@FreeBSD.org  Thu Dec 24 04:55:08 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id D7AE21065696
	for <freebsd-gnats-submit@FreeBSD.org>; 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 <freebsd-gnats-submit@FreeBSD.org>; 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 <freebsd-gnats-submit@FreeBSD.org>; 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 <denis@tikuts.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: strptime confuses July with June with the fr_FR locale
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         141939
>Category:       kern
>Synopsis:       [libc] [patch] strptime(3) confuses July with June with the fr_FR locale
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    edwin
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 24 05:00:12 UTC 2009
>Closed-Date:    Tue Oct 19 21:08:45 UTC 2010
>Last-Modified:  Tue Oct 19 21:10:11 UTC 2010
>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 <time.h>
#include <locale.h>
#include <string.h>
#include <stdio.h>

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:
State-Changed-From-To: open->analyzed 
State-Changed-By: edwin 
State-Changed-When: Wed Jan 27 11:49:00 UTC 2010 
State-Changed-Why:  
Confirmed. 


Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Wed Jan 27 11:49:00 UTC 2010 
Responsible-Changed-Why:  
I'll handle it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141939 
State-Changed-From-To: analyzed->patched 
State-Changed-By: edwin 
State-Changed-When: Sun May 9 22:01:45 UTC 2010 
State-Changed-Why:  
Fixed in head, MFC in a week. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141939 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141939: commit references a PR
Date: Sun,  9 May 2010 22:01:45 +0000 (UTC)

 Author: edwin
 Date: Sun May  9 22:01:35 2010
 New Revision: 207830
 URL: http://svn.freebsd.org/changeset/base/207830
 
 Log:
   strptime(3) confused July with June with the fr_FR locale.
   
   When parsing the month "juillet" (abbr "jul"), %B recognized it as
   "juin" (abbr "jui") because the full name of the month names is
   checked at the same time as the abbrevation.
   
   The new behaviour checks the full names first before checking the
   abbrevation names.
   
   PR:		kern/141939
   Submitted by:	Denis Chatelain <denis@tikuts.com>
   MFC after:	1 week
 
 Modified:
   head/lib/libc/stdtime/strptime.c
 
 Modified: head/lib/libc/stdtime/strptime.c
 ==============================================================================
 --- head/lib/libc/stdtime/strptime.c	Sun May  9 21:34:05 2010	(r207829)
 +++ head/lib/libc/stdtime/strptime.c	Sun May  9 22:01:35 2010	(r207830)
 @@ -408,6 +408,14 @@ label:
  					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)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: edwin 
State-Changed-When: Tue Oct 19 21:08:25 UTC 2010 
State-Changed-Why:  
MFC to stable/8 and stable/7 done. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141939 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141939: commit references a PR
Date: Tue, 19 Oct 2010 21:04:50 +0000 (UTC)

 Author: edwin
 Date: Tue Oct 19 21:04:45 2010
 New Revision: 214079
 URL: http://svn.freebsd.org/changeset/base/214079
 
 Log:
   MFC of r207830
   
   strptime(3) confused July with June with the fr_FR locale.
   
   When parsing the month "juillet" (abbr "jul"), %B recognized it as
   "juin" (abbr "jui") because the full name of the month names is
   checked at the same time as the abbrevation.
   
   The new behaviour checks the full names first before checking the
   abbrevation names.
   
   PR:             kern/141939
   Submitted by:   Denis Chatelain <denis@tikuts.com>
 
 Modified:
   stable/8/lib/libc/stdtime/strptime.c
 Directory Properties:
   stable/8/lib/libc/   (props changed)
   stable/8/lib/libc/locale/   (props changed)
   stable/8/lib/libc/stdtime/   (props changed)
   stable/8/lib/libc/sys/   (props changed)
 
 Modified: stable/8/lib/libc/stdtime/strptime.c
 ==============================================================================
 --- stable/8/lib/libc/stdtime/strptime.c	Tue Oct 19 21:02:05 2010	(r214078)
 +++ stable/8/lib/libc/stdtime/strptime.c	Tue Oct 19 21:04:45 2010	(r214079)
 @@ -408,6 +408,14 @@ label:
  					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)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/141939: commit references a PR
Date: Tue, 19 Oct 2010 21:05:27 +0000 (UTC)

 Author: edwin
 Date: Tue Oct 19 21:05:22 2010
 New Revision: 214080
 URL: http://svn.freebsd.org/changeset/base/214080
 
 Log:
   MFC of r207830
   
   strptime(3) confused July with June with the fr_FR locale.
   
   When parsing the month "juillet" (abbr "jul"), %B recognized it as
   "juin" (abbr "jui") because the full name of the month names is
   checked at the same time as the abbrevation.
   
   The new behaviour checks the full names first before checking the
   abbrevation names.
   
   PR:             kern/141939
   Submitted by:   Denis Chatelain <denis@tikuts.com>
 
 Modified:
   stable/7/lib/libc/stdtime/strptime.c
 Directory Properties:
   stable/7/lib/libc/   (props changed)
   stable/7/lib/libc/stdtime/   (props changed)
 
 Modified: stable/7/lib/libc/stdtime/strptime.c
 ==============================================================================
 --- stable/7/lib/libc/stdtime/strptime.c	Tue Oct 19 21:04:45 2010	(r214079)
 +++ stable/7/lib/libc/stdtime/strptime.c	Tue Oct 19 21:05:22 2010	(r214080)
 @@ -408,6 +408,14 @@ label:
  					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)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
