This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/6985] New: setlocale(LC_X, NULL) returns invalid pointer with "C" locale, according to mudflap


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]