0

In my C project, I have a shared library compiled with -fPIC that contains several static data structures declared at global scope, including, let's say,

static struct mydata;

This library calls a function

void myfunc() {
char foo[2048] = {0};
...
}

which is defined in a different shared library.

When I compile my main application, I link in the shared library that defines myfunc(). At runtime, the main application loads the other shared library containing the static data structures using dlopen().

Calling myfunc() from the shared library in which mydata is declared results in mydata being at least partially overwritten.

After snooping with gdb it is clear that the local array foo is placed in memory in such a way that it overlaps with the address of mydata, so when the array is initialized to 0, so too is mydata.

How could this be? Am I doing something that is unhandled by the compiler?

Note that I am running Red Hat on 64-bit architecture using gcc 4.6.

Chris
  • 474
  • 2
  • 8
  • 22
  • 1
    I don't believe the compiler will put a global variable within 2 kb of the stack (at least not in the direction the stack is growing towards). – EOF Apr 07 '14 at 22:15
  • I wouldn't think so either, that's why I'm here. If I break at the function call and print the addresses of both objects in gdb I can see that the address of the struct is right on top of the range of addresses for the local array. – Chris Apr 07 '14 at 22:21
  • You could try reserving more memory for the stack (apparently via `setrlimit` on Linux, for example) – EOF Apr 07 '14 at 22:28
  • Unless you seriously messed up the `struct mydata`'s size somehow (get different definitions in the various files), or you *really* wrote as above (that just declares a structure tag, if the compiler accepts that as-is it is a compiler bug)... – vonbrand Apr 13 '14 at 01:52

1 Answers1

0

How could this be?

I've seen this happen ... when some other routine reserved 8MB buffer on the stack, and overflowed stack into the data region.

If the problem goes away with ulimit -s unlimited, chances are that's what is happening to you as well.

At the place where mydata has just been corrupted, do these commands:

(gdb) p $rsp
(gdb) p $rbp
(gdb) p &mydata
(gdb) p &foo[0]
(gdb) info var mydata

and update your question with results.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362