kern/141939: strptime confuses July with June with the fr_FR locale

Denis Chatelain denis at tikuts.com
Thu Dec 24 05:00:13 UTC 2009


>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 at 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:
>Unformatted:


More information about the freebsd-bugs mailing list