Segmentation fault in tccelf.c:2189, strcmp

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Segmentation fault in tccelf.c:2189, strcmp

Diego Bauche Madero
Here is a bug i came across when compiling an application, i don't
really know where it is, though i thought it may help if i give you guys
some information:

-----
Starting program: /home/rewt/tcc-0.9.23/tcc -IGL
/usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
/usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
libellenbeck-fract libellenbeck-fract.c

Program received signal SIGSEGV, Segmentation fault.
0xb7e76c28 in strcmp () from /lib/tls/libc.so.6
(gdb) x/i $pc
0xb7e76c28 <strcmp+8>:  mov    (%ecx),%al
(gdb) i r ecx eax
ecx            0x4f6fb954       1332722004
eax            0x26     38
(gdb) x/x *$ecx
Cannot access memory at address 0x4f6fb954
(gdb) bt
#0  0xb7e76c28 in strcmp () from /lib/tls/libc.so.6
#1  0x0805c3fa in tcc_load_dll (s1=0x8070008, fd=8, filename=0xbfd66900
"/usr/lib/libGL.so.1", level=1) at tccelf.c:2189
#2  0x0805bf0c in tcc_add_file_internal (s1=0x8070008,
filename=0xbfd66900 "/usr/lib/libGL.so.1", flags=1) at tcc.c:9923
#3  0x0805c0f5 in tcc_add_dll (s=0x8070008, filename=0x808cb11
"libGL.so.1", flags=2) at tcc.c:9983
#4  0x0805c385 in tcc_load_dll (s1=0x8070008, fd=7, filename=0xbfd696c1
"/usr/X11R6/lib/libGLU.so", level=0) at tccelf.c:2192
#5  0x0805bf0c in tcc_add_file_internal (s1=0x8070008,
filename=0xbfd696c1 "/usr/X11R6/lib/libGLU.so", flags=0) at tcc.c:9923
#6  0x0805e653 in main (argc=12, argv=0xbfd67714) at tcc.c:10642
----

(I took away the `static' definition of tcc_load_dll by the way)

At tccelf.c line 2182:
----
    /* load all referenced DLLs */
    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
        switch(dt->d_tag) {
        case DT_NEEDED:
            name = dynstr + dt->d_un.d_val;
            for(i = 0; i < s1->nb_loaded_dlls; i++) {
                dllref = s1->loaded_dlls[i];
                if (!strcmp(name, dllref->name))
                    goto already_loaded;
            }
----

During the strcmp(name,dllref->name) call, `name' points to 0x4f6fb954,
which is not a valid address, being dynstr = 0x80d4fe8 and dt->d-un =
{d_val = 0x4762696c, d_ptr = 0x4762696c}

If more information is needed (i.e. core file), please let me know.

Cheers
- Diego Bauche Madero



_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp

crcthought
On Tue, 2005-10-25 at 17:06 -0400, Diego Bauche Madero wrote:

>     /* load all referenced DLLs */
>     for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
>         switch(dt->d_tag) {
>         case DT_NEEDED:
>             name = dynstr + dt->d_un.d_val;
>             for(i = 0; i < s1->nb_loaded_dlls; i++) {
>                 dllref = s1->loaded_dlls[i];
>                 if (!strcmp(name, dllref->name))
>                     goto already_loaded;
>             }
> ----
>
> During the strcmp(name,dllref->name) call, `name' points to 0x4f6fb954,
> which is not a valid address, being dynstr = 0x80d4fe8 and dt->d-un =
> {d_val = 0x4762696c, d_ptr = 0x4762696c}

If dynstr and dt->d_un.d_val are the values you say they are, then name
is quite correct.  You added the pointers!  I see no reason at all to
fault the compiler.  You should also likely want to use strncmp so you
have some sort of upper bound on your string compare, just in case.

> If more information is needed (i.e. core file), please let me know.

Have you compiled with another compiler to verify that this isn't a
problem in the source and not the compiler?





_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp

Diego Bauche Madero
Evan Langlois wrote:

>On Tue, 2005-10-25 at 17:06 -0400, Diego Bauche Madero wrote:
>  
>
>>    /* load all referenced DLLs */
>>    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
>>        switch(dt->d_tag) {
>>        case DT_NEEDED:
>>            name = dynstr + dt->d_un.d_val;
>>            for(i = 0; i < s1->nb_loaded_dlls; i++) {
>>                dllref = s1->loaded_dlls[i];
>>                if (!strcmp(name, dllref->name))
>>                    goto already_loaded;
>>            }
>>----
>>
>>During the strcmp(name,dllref->name) call, `name' points to 0x4f6fb954,
>>which is not a valid address, being dynstr = 0x80d4fe8 and dt->d-un =
>>{d_val = 0x4762696c, d_ptr = 0x4762696c}
>>    
>>
>
>If dynstr and dt->d_un.d_val are the values you say they are, then name
>is quite correct.  You added the pointers!  I see no reason at all to
>fault the compiler.  You should also likely want to use strncmp so you
>have some sort of upper bound on your string compare, just in case.
>
>  
>
----
(gdb) x/i $pc

0xb7e76c28 <strcmp+8>:  mov    (%ecx),%al
(gdb) x/x *$ecx
Cannot access memory at address 0x4f6fb954
(gdb) set $dynstr=0x80d4fe8
(gdb) set $d_val=0x4762696c
(gdb) p/x $dynstr+$d_val
$1 = 0x4f6fb954
(gdb)
----
       
As you can see, `name' points to the address i said, and of course, being not an accesable address, the program just sends SIGSEGV.
Anyway, the core file and tcc ELF executable binary (compiled with glibc 2.3.4) can be found at http://genexx.org/tcc_strcmp.tbz2


>>If more information is needed (i.e. core file), please let me know.
>>    
>>
>
>  
>
>Have you compiled with another compiler to verify that this isn't a
>problem in the source and not the compiler?
>
>
>  
>
Yes, i have:

----
$ tcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
/usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
libellenbeck-fract libellenbeck-fract.c
Segmentation fault
$ gcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
/usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
libellenbeck-fract libellenbeck-fract.c
$ ls libellenbeck-fract
libellenbeck-fract*
$ tcc -v; gcc -v
tcc version 0.9.23
Reading specs from /usr/pp/lib/gcc-lib/i686-pc-linux-gnu/3.3/specs
Configured with: ../configure --prefix=/usr/pp
Thread model: posix
gcc version 3.3
$ uname -mps
Linux i686 Pentium III (Katmai)
$
----

>
>
>_______________________________________________
>Tinycc-devel mailing list
>[hidden email]
>http://lists.nongnu.org/mailman/listinfo/tinycc-devel
>
>
>
>  
>


Cheers
- Diego Bauche Madero


_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp

crcthought
On Tue, 2005-10-25 at 21:25 -0400, Diego Bauche Madero wrote:

> As you can see, `name' points to the address i said, and of course, being not an accesable address, the program just sends SIGSEGV.
> Anyway, the core file and tcc ELF executable binary (compiled with glibc 2.3.4) can be found at http://genexx.org/tcc_strcmp.tbz2

The question isn't if name is that address or not, the question is why
isn't that address within the application's memory map.

> $ tcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
> /usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
> libellenbeck-fract libellenbeck-fract.c
> Segmentation fault
> $ gcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
> /usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
> libellenbeck-fract libellenbeck-fract.c

Well, it would seem to be a bug.  However, rogue pointers can cause
really odd problems that may work on some systems and not others, or may
only show on certain compilation or optimization options, etc.

Can you narrow down the issue into a smaller test case, preferably
without all the library dependancies?  Is the source available?  Its
usually easier to look at the source than trying to look through a core
file.

-- Evan




_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp - bugfix, i think

Diego Bauche Madero
Evan Langlois wrote:

>On Tue, 2005-10-25 at 21:25 -0400, Diego Bauche Madero wrote:
>
>  
>
>>As you can see, `name' points to the address i said, and of course, being not an accesable address, the program just sends SIGSEGV.
>>Anyway, the core file and tcc ELF executable binary (compiled with glibc 2.3.4) can be found at http://genexx.org/tcc_strcmp.tbz2
>>    
>>
>
>The question isn't if name is that address or not, the question is why
>isn't that address within the application's memory map.
>
>  
>
Oh, i got your point.

>>$ tcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
>>/usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
>>libellenbeck-fract libellenbeck-fract.c
>>Segmentation fault
>>$ gcc -IGL /usr/X11R6/lib/libX11.so.6 /usr/X11R6/lib/libXext.so.6
>>/usr/X11R6/lib/libGLU.so /usr/X11R6/lib/libglut.so.3 -lGL -IGLU -lm -o
>>libellenbeck-fract libellenbeck-fract.c
>>    
>>
>
>Well, it would seem to be a bug.  However, rogue pointers can cause
>really odd problems that may work on some systems and not others, or may
>only show on certain compilation or optimization options, etc.
>
>Can you narrow down the issue into a smaller test case, preferably
>without all the library dependancies?  Is the source available?  Its
>usually easier to look at the source than trying to look through a core
>file.
>
>-- Evan
>
>  
>
I've been looking into it a little bit, this bug is easy to reproduce.

This is very small test case:
First of all, i've seen that this has nothing to do with my code or
specific code inside the specific libraries i was using.

Apparently, if the shared libraries are compiled with gcc (i have tried
two versions, 3.3 and 4.0.1) tcc faults, but if they are compiled with
tcc, it wont:

fault:
----
cd /usr/lib
gcc -shared -o ./1.so /tmp/1.c
gcc -shared -o ./2.so /tmp/2.c
gcc -shared -o ./3.so /tmp/2.c
gcc -shared -o ./3.so /tmp/3.c
gcc -shared -o ./4.so /tmp/4.c
gcc -shared -o ./foo.so /tmp/foo.c 1.so 2.so 3.so 4.so
tcc /usr/lib/foo.so
----


and source codes:
1.c: int a;
2.c: int b;

3.c: int c;
4.c: int d;
foo.c: main() {}


I think gcc is doing something weird with the SHT_DYNAMIC section of a
shared library object (though it could be a tinyc bug somewhere else, i
don't know).

in tccelf:2125
        case SHT_DYNAMIC:
            nb_dts = sh->sh_size / sizeof(Elf32_Dyn);
            dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
            break;

of course, `dynamic' gets the section memory, `nb_dts' has the number of
times to read the dynamic section entries over the for() loop that
checks if the referenced dll is already loaded and if not, it gets
loaded, etc.

The problem here is that when /usr/lib/4.so gets read, for some strange
cause the dynamic section over the shared library object appears to have
more memory to what it is supossed to have. Here's a test (i added the
debugging messages inside the "for(i = 0; i < s1->nb_loaded_dlls; i++)
{" loop btw) :

----
localhost lib # ~rewt/tcc-0.9.23/tcc /usr/lib/foo.so
[...]
loading dll '4.so'
[...]
Trying to access to 0x8080ac9 (Being dynstr 0x8080a68, dt 0x8080748,
dt->d_un 00000061 and dt->d_un.d_val = 97 and dt->d_tag 1
Trying to access to 0x74356ed4 (Being dynstr 0x8080a68, dt 0x8080810,
dt->d_un 6c2d646c and dt->d_un.d_val = 1814914156 and dt->d_tag 1
Segmentation fault
----
So, the last dynamic section entry APPEARS to contain bogus memory. This
could be some internal tinyc bug, but i wouldn't count on that, because
if i compile the shared library objects using tcc itself, it doesn't fault.

To make the story short, i tried this on several machines, just do the
test yourself.
Anyhow, here's a quick fix (on the last cvs revision) to deal with this
odd case:

--- tinycc-orig/tccelf.c        2005-10-27 02:43:35.000000000 -0400
+++ tinycc/tccelf.c     2005-10-27 02:55:19.000000000 -0400
@@ -2184,6 +2184,8 @@ static int tcc_load_dll(TCCState *s1, in
         switch(dt->d_tag) {
         case DT_NEEDED:
             name = dynstr + dt->d_un.d_val;
+            if ((Elf32_Dyn *)name > dynamic + (nb_dts * sizeof(Elf32_Dyn)))
+                goto the_end;
             for(i = 0; i < s1->nb_loaded_dlls; i++) {
                 dllref = s1->loaded_dlls[i];
                 if (!strcmp(name, dllref->name))



>
>_______________________________________________
>Tinycc-devel mailing list
>[hidden email]
>http://lists.nongnu.org/mailman/listinfo/tinycc-devel
>
>
>
>  
>

Cheers
- Diego Bauche Madero


_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp - bugfix, i think

crcthought
On Thu, 2005-10-27 at 03:06 -0400, Diego Bauche Madero wrote:

> --- tinycc-orig/tccelf.c        2005-10-27 02:43:35.000000000 -0400
> +++ tinycc/tccelf.c     2005-10-27 02:55:19.000000000 -0400
> @@ -2184,6 +2184,8 @@ static int tcc_load_dll(TCCState *s1, in
>          switch(dt->d_tag) {
>          case DT_NEEDED:
>              name = dynstr + dt->d_un.d_val;
> +            if ((Elf32_Dyn *)name > dynamic + (nb_dts * sizeof(Elf32_Dyn)))
> +                goto the_end;
>              for(i = 0; i < s1->nb_loaded_dlls; i++) {
>                  dllref = s1->loaded_dlls[i];
>                  if (!strcmp(name, dllref->name))
>

WOW - Excellent work.  I can't honestly say if the fault is TCC or GCC,
or if they just don't like each other mutually, but a patch that makes
TCC work both ways is excellent news.

Now I'm wondering if that patch will make tcc work with boehm's GC.  Its
entirely possible that my previous problems with that library were due
to it being compiled with GCC, and considering that a GC will hit most
all of RAM looking for roots, it is very likely to hit such a bug.

Hopefully it will get comitted to CVS.





_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: BUGFIX: Segmentation fault in tccelf.c:2189, strcmp

Diego Bauche Madero
Now that i look at the patch again, seems like i commited an error, sorry.
The patch must not do the goto the_end, but a break, otherwise it will
just go on without loading anything. Apparently the if statement is true
on every single shared library, so, here's the working patch:

--- tinycc-orig/tccelf.c        2005-10-27 02:43:35.000000000 -0400
+++ tinycc/tccelf.c     2005-10-27 02:55:19.000000000 -0400
@@ -2184,6 +2184,8 @@ static int tcc_load_dll(TCCState *s1, in
         switch(dt->d_tag) {
         case DT_NEEDED:
             name = dynstr + dt->d_un.d_val;
+            if ((Elf32_Dyn *)name > dynamic + (nb_dts * sizeof(Elf32_Dyn)))
+                break;
             for(i = 0; i < s1->nb_loaded_dlls; i++) {
                 dllref = s1->loaded_dlls[i];
                 if (!strcmp(name, dllref->name))



Cheers
- Diego Bauche Madero

Evan Langlois wrote:

>On Thu, 2005-10-27 at 03:06 -0400, Diego Bauche Madero wrote:
>
>  
>
>>--- tinycc-orig/tccelf.c        2005-10-27 02:43:35.000000000 -0400
>>+++ tinycc/tccelf.c     2005-10-27 02:55:19.000000000 -0400
>>@@ -2184,6 +2184,8 @@ static int tcc_load_dll(TCCState *s1, in
>>         switch(dt->d_tag) {
>>         case DT_NEEDED:
>>             name = dynstr + dt->d_un.d_val;
>>+            if ((Elf32_Dyn *)name > dynamic + (nb_dts * sizeof(Elf32_Dyn)))
>>+                goto the_end;
>>             for(i = 0; i < s1->nb_loaded_dlls; i++) {
>>                 dllref = s1->loaded_dlls[i];
>>                 if (!strcmp(name, dllref->name))
>>
>>    
>>
>
>WOW - Excellent work.  I can't honestly say if the fault is TCC or GCC,
>or if they just don't like each other mutually, but a patch that makes
>TCC work both ways is excellent news.
>
>Now I'm wondering if that patch will make tcc work with boehm's GC.  Its
>entirely possible that my previous problems with that library were due
>to it being compiled with GCC, and considering that a GC will hit most
>all of RAM looking for roots, it is very likely to hit such a bug.
>
>Hopefully it will get comitted to CVS.
>
>
>
>
>
>_______________________________________________
>Tinycc-devel mailing list
>[hidden email]
>http://lists.nongnu.org/mailman/listinfo/tinycc-devel
>
>
>
>  
>


_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp - bugfix, i think

grischka
In reply to this post by Diego Bauche Madero
> for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
>       ...
>       name = dynstr + dt->d_un.d_val;
> +    if ((Elf32_Dyn *)name > dynamic + (nb_dts * sizeof(Elf32_Dyn)))
> +        break;

Hm, looks more like the strong sort of medicine....
Guess I would try this pill first:
http://lists.gnu.org/archive/html/tinycc-devel/2005-06/msg00026.html

--- grischka

Btw, upper array boundary is just: "pArray + nElements", also
compare of pointers into different memory regions is generally
not useful (pointer into dynstr > pointer into dynamic). Also the
end of the array is already outside, so, if at all, it would be >=,
not >  

What you probably meant was:
    for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
+        if (dt >= dynamic + nb_dts)
+            break;

which of course is logically redundant, as long as 'i' wasn't changed
unexpectedly further down.

However, it probably happens more often than you might think, that bugs
are fixed by just some more bugs being added. As such, a bug in the right
place can make many users happy ;)








_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Segmentation fault in tccelf.c:2189, strcmp - bugfix, i think

Fabrice Bellard
grischka wrote:
> Hm, looks more like the strong sort of medicine....
> Guess I would try this pill first:
> http://lists.gnu.org/archive/html/tinycc-devel/2005-06/msg00026.html
>
> --- grischka

Thank you - I commited the fix.

Fabrice.


_______________________________________________
Tinycc-devel mailing list
[hidden email]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel