This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/6985] New: setlocale(LC_X, NULL) returns invalid pointer with "C" locale, according to mudflap
- From: "poletto at jeuxvideo dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 25 Oct 2008 11:54:37 -0000
- Subject: [Bug libc/6985] New: setlocale(LC_X, NULL) returns invalid pointer with "C" locale, according to mudflap
- Reply-to: sourceware-bugzilla at sourceware dot org
Well, all is in the title. I didn't try with the CVS version (seems somewhat
complicated to build a gcc/glibc toolchain) but i think this part didn't change
for a while.
The error can occur for example when doing strlen(setlocale(LC_X, NULL)) or
strcpy(out, setlocale(LC_X, NULL)). Strangely it doesn't happen with *printf.
I have reimplemented strlen() to see what happened.
Note that even if there is an error, the string data is correct (that's why this
bug isn't really noticeable).
Also, I can't be sure it's not a mudflap problem, for example an issue with
detecting errors inside dynamic libraries.
This program executes my_strlen and prints strings from different locations and
from the return of setlocale(LC_X, NULL)
--- code ----
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
static size_t my_strlen(const char * s)
{
const char * ptr;
ptr = s;
/* *ptr => invalid read
*/
while (*ptr != '\0')
{
ptr++;
}
return ptr - s;
}
static void print_s(const char * s)
{
/* No invalid read with the printf itself
*/
printf("[%p] \"%s\" (%u)\n", s, s, my_strlen(s));
}
static const char from_global[] = "X";
int main(void)
{
char * from_heap;
char from_stack[] = "X";
const char * old_locale;
from_heap = strdup("X");
print_s(from_heap);
print_s(from_stack);
print_s(from_global);
print_s("X");
//setlocale(LC_ALL, "");
old_locale = setlocale(LC_TIME, NULL);
print_s(old_locale);
free(from_heap);
return 0;
}
--- end code ----
Gcc version :
$ gcc --version
gcc (Gentoo 4.3.1-r1 p1.1) 4.3.1
Glibc version :
$ equery l glibc
...
[I--] [ ~] sys-libs/glibc-2.8_p20080602 (2.2)
Command to build :
$ gcc -std=gnu99 -Wall -W -fmudflap test_setlocale.c -lmudflap -rdynamic -o
test_setlocale
With setlocale(LC_ALL, ""); instruction commented, the locale stays to the "C"
default, so the error appears. Two errors for the two "*ptr" access in my_strlen
(two characters to read in string "C")
$ ./test_setlocale
[0x706510] "X" (1)
[0x7fff1a25c190] "X" (1)
[0x400e53] "X" (1)
[0x400e81] "X" (1)
*******
mudflap violation 1 (check/read): time=1224934449.516218 ptr=0x7f2811a5d693 size=1
pc=0x7f2811c9fc71 location=`test_setlocale.c:13:12 (my_strlen)'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.1/libmudflap.so.0(__mf_check+0x41)
[0x7f2811c9fc71]
./test_setlocale(__wrap_main+0x18f) [0x400bbf]
./test_setlocale [0x400c0b]
number of nearby objects: 0
*******
mudflap violation 2 (check/read): time=1224934449.516270 ptr=0x7f2811a5d694 size=1
pc=0x7f2811c9fc71 location=`test_setlocale.c:13:12 (my_strlen)'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.1/libmudflap.so.0(__mf_check+0x41)
[0x7f2811c9fc71]
./test_setlocale(__wrap_main+0x18f) [0x400bbf]
./test_setlocale [0x400c0b]
number of nearby objects: 0
[0x7f2811a5d693] "C" (1)
With setlocale(LC_ALL, "") uncommented, and with a non-"C" locale set in the
environment, there's no problem
$ locale
LANG=fr_FR.iso88591
LC_CTYPE="fr_FR.iso88591"
LC_NUMERIC="fr_FR.iso88591"
LC_TIME="fr_FR.iso88591"
LC_COLLATE="fr_FR.iso88591"
LC_MONETARY="fr_FR.iso88591"
LC_MESSAGES="fr_FR.iso88591"
LC_PAPER="fr_FR.iso88591"
LC_NAME="fr_FR.iso88591"
LC_ADDRESS="fr_FR.iso88591"
LC_TELEPHONE="fr_FR.iso88591"
LC_MEASUREMENT="fr_FR.iso88591"
LC_IDENTIFICATION="fr_FR.iso88591"
LC_ALL=fr_FR.iso88591
$ ./test_setlocale
[0x7065d0] "X" (1)
[0x7fff618d5810] "X" (1)
[0x400e73] "X" (1)
[0x400ea1] "X" (1)
[0x70b960] "fr_FR.iso88591" (14)
But with a locale set to "C" or "POSIX" in the environment, same problem as before
$ LC_ALL="C" ./test_setlocale
[0x7065d0] "X" (1)
[0x7fff318db820] "X" (1)
[0x400e73] "X" (1)
[0x400ea1] "X" (1)
*******
mudflap violation 1 (check/read): time=1224934867.981572 ptr=0x7f14290da693 size=1
pc=0x7f142931cc71 location=`test_setlocale.c:13:12 (my_strlen)'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.1/libmudflap.so.0(__mf_check+0x41)
[0x7f142931cc71]
./test_setlocale(__wrap_main+0x18f) [0x400bbf]
./test_setlocale [0x400c0b]
number of nearby objects: 0
*******
mudflap violation 2 (check/read): time=1224934867.981621 ptr=0x7f14290da694 size=1
pc=0x7f142931cc71 location=`test_setlocale.c:13:12 (my_strlen)'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.1/libmudflap.so.0(__mf_check+0x41)
[0x7f142931cc71]
./test_setlocale(__wrap_main+0x18f) [0x400bbf]
./test_setlocale [0x400c0b]
number of nearby objects: 0
[0x7f14290da693] "C" (1)
I tried to analyze the setlocale() code, i saw that "C" and "POSIX" locale names
were read only global strings, so not memory locations to be freed or modified.
Other locale names are strdup'ed. I didn't invistigate too long but it seems
that everytime a free() is done on a locale name, it's well checked if the
pointer is not the one to "C" global read only string. Then i don't know.
--
Summary: setlocale(LC_X, NULL) returns invalid pointer with "C"
locale, according to mudflap
Product: glibc
Version: 2.8
Status: NEW
Severity: minor
Priority: P2
Component: libc
AssignedTo: drepper at redhat dot com
ReportedBy: poletto at jeuxvideo dot com
CC: glibc-bugs at sources dot redhat dot com
GCC build triplet: x86_64 gentoo linux 2.6.26
GCC host triplet: x86_64 gentoo linux 2.6.26
GCC target triplet: x86_64 gentoo linux 2.6.26
http://sourceware.org/bugzilla/show_bug.cgi?id=6985
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.