This is the mail archive of the
libc-locales@sourceware.org
mailing list for the GNU libc locales project.
[Bug localedata/12788] New: [PATCH] setlocale sets the locale ofLC_ALL incorrect to 'C' in some cases (/when LC_CTYPE is used)
- From: "bug_rh at spam dot wizbit.be" <sourceware-bugzilla at sourceware dot org>
- To: libc-locales at sources dot redhat dot com
- Date: Fri, 20 May 2011 08:00:21 +0000
- Subject: [Bug localedata/12788] New: [PATCH] setlocale sets the locale ofLC_ALL incorrect to 'C' in some cases (/when LC_CTYPE is used)
- Auto-submitted: auto-generated
http://sourceware.org/bugzilla/show_bug.cgi?id=12788
Summary: [PATCH] setlocale sets the locale of LC_ALL incorrect
to 'C' in some cases (/when LC_CTYPE is used)
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: localedata
AssignedTo: libc-locales@sources.redhat.com
ReportedBy: bug_rh@spam.wizbit.be
Created attachment 5739
--> http://sourceware.org/bugzilla/attachment.cgi?id=5739
patch - update the condition in set_composite_name
There is a bug in setlocale that can result in LC_ALL being incorrectly set to
LC_ALL.
Test case:
$ cat bug-setlocale.c
#include <stdio.h>
#include <locale.h>
int main () {
printf("setlocale(LC_ALL, \"\") = %s\n", setlocale(LC_ALL, ""));
printf("setlocale(LC_CTYPE, \"\") = %s\n", setlocale(LC_CTYPE, ""));
printf("setlocale(LC_ALL, NULL) = %s\n", setlocale(LC_ALL, NULL));
printf("setlocale(LC_NUMERIC, \"\") = %s\n", setlocale(LC_NUMERIC,
""));
printf("setlocale(LC_ALL, NULL) = %s\n", setlocale(LC_ALL, NULL));
setlocale(LC_ALL, "C");
printf("setlocale(LC_ALL, NULL) = %s\n", setlocale(LC_ALL, NULL));
printf("setlocale(LC_CTYPE, NULL) = %s\n", setlocale(LC_CTYPE, NULL));
}
Running it:
$ env -i LC_CTYPE=en_US ./bug-setlocale
setlocale(LC_ALL, "") = LC_CTYPE=en_US;LC_NUMERIC=C;LC_.... # => expected
setlocale(LC_CTYPE, "") = en_US # => expected
setlocale(LC_ALL, NULL) = LC_CTYPE=en_US;LC_NUMERIC=C;LC_... # => expected
setlocale(LC_NUMERIC, "") = C # => expected
setlocale(LC_ALL, NULL) = C # => not expected;
expected value: LC_CTYPE=en_US;LC_NUMERIC=C;LC_...
setlocale(LC_ALL, NULL) = C # => expected
setlocale(LC_CTYPE, NULL) = en_US # => not expected;
expected value: 'C'
Important when running the test case:
a) the locale en_US needs to be installed/needs to exists on the system
b) only the environment variable LC_CTYPE should be set (LC_ALL, LANG,
LC_COLLATE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME need to be unset)
I traced the problem to the file locale/setlocale.c, function:
new_composite_name, line: 150-160:
for (i = 0; i < __LC_LAST; ++i)
if (i != LC_ALL)
{
const char *name = (category == LC_ALL ? newnames[i] :
category == i ? newnames[0] :
_nl_global_locale.__names[i]);
last_len = strlen (name);
cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
if (i > 0 && same && strcmp (name, newnames[0]) != 0)
same = 0;
}
The problem is the condition on line 158: the 'i > 0' is incorrect.
The condition should be: ((category == LC_ALL && i > 0) || (category != LC_ALL
&& i != category))
The reasoning/the explanation (using the above test case):
A) setlocale(LC_ALL, ""):
This calls new_composite_name with category = 6 and newnames an array of 13
elements.
For i = 0: name = newnames[0] => strcmp(name, newnames[0]) != 0 can be
skipped
For i = 1: name = newnames[1] => strcmp(name, newnames[1]) != 0 can not be
skipped
B) setlocale(LC_CTYPE, "")
This calls new_composite_name with category = 0 and newnames an array of 1
element
For i = 0: name = newnames[0] => strcmp(name, newnames[0]) != 0 can be
skipped
For i = 1: name = _nl_global_locale.__names[1] => strcmp(name, newnames[0]) !=
0 can not be skipped
C) setlocale(LC_NUMERIC, "")
This calls new_composite_name with category = 1 and newnames an array of 1
element
For i = 0: name = _nl_global_locale.__names[0] => strcmp(name, newnames[0]) !=
0 can not be skipped
For i = 1: name = newnames[0] => strcmp(name, newnames[0]) != 0 can be skipped
==> strcmp(name, newnames[0]) != 0 can only be skipped if:
* category == LC_ALL and i == 0
* category != LC_ALL and i == category
The bug was (I believe) introduced in commit
4b10dd6c1959577f57850ca427a94fe22b9f3299 (dated Tue, 31 Aug 1999 07:04:41 +0000
(07:04 +0000))
Attached is a patch which updates the condition.
The output after the patch:
$ env -i LC_CTYPE=en_US ./bug-setlocale
setlocale(LC_ALL, "") =
LC_CTYPE=en_US;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C
setlocale(LC_CTYPE, "") = en_US
setlocale(LC_ALL, NULL) =
LC_CTYPE=en_US;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C
setlocale(LC_NUMERIC, "") = C
setlocale(LC_ALL, NULL) =
LC_CTYPE=en_US;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C
setlocale(LC_ALL, NULL) = C
setlocale(LC_CTYPE, NULL) = C
--
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.