[Mono-list] Mono.Unix.Native.Syscall.readlink memory corruption

Jonathan Pryor jonpryor at vt.edu
Tue Mar 14 13:43:49 EST 2006

On Tue, 2006-03-14 at 11:33 +0000, Colin JN Breame wrote:
> On Tuesday 14 March 2006 00:16, Jonathan Gilbert wrote:
> > At 04:12 PM 13/03/2006 -0500, Gonzalo Paniagua Javier wrote:
> > >On Mon, 2006-03-13 at 17:32 +0000, Colin JN Breame wrote:
> > >> using System.Text;
> > >> public class main_t {
> > >>   public static void Main() {
> > >>     for (int i=0; i<10000; i++) {
> > >>       StringBuilder buf = new StringBuilder();
> > >>       Mono.Unix.Native.Syscall.readlink("path/to/link/file", buf);
> > >>     }
> > >>   }
> > >> }
> > >
> > >Confirmed. I get the same error.
> >
> > Don't you need to give the StringBuilder a capacity first? Is the default
> > capacity documented, and documented to be large enough for the return value
> > of readlink()?
> >
> Look like the default capacity is the capacity of the StringBuilder passed, so 
> setting the Length of the buffer seems to solve the problem.  A test for zero 
> length would probably be useful:

The test isn't useful, as readlink(2) _already_ does this check (and is
documented as returning -1 with errno = EINVAL if the buffer size is
incorrect).  Furthermore, the default StringBuilder capacity is 16, not
0, so 0 really shouldn't ever be passed.

What's more confusing is this: if I run your program inside gdb, set a
breakpoint inside Mono_Posix_Syscall_readlink, and print out `len' (the
buffer length argument), I get bizarre random values (e.g. 290704).

*That* is the fundamental problem: the buffer length argument doesn't
match the StringBuilder capacity.

Oddly, if I use the Syscall.readlink(string,StringBuilder,ulong)
overload, I don't see any problems at all.

Odder, all Syscall.readlink(string,StringBuilder) does is invoke
Syscall.readlink(string,StringBuilder,ulong) with the final argument set
to (ulong)StringBuilder.Capacity.

I have no idea why this is happening (a botched svn build?).
> As in the C world we known MAX_PATH, might it not be better to change the 
> semantics of the call so that it returns the path?

MAX_PATH is always a bad idea, as it changes from filesystem to
filesystem.  Also, some systems don't have a MAX_PATH, such as GNU HURD.

> On a related note:  if a C function mallocs some memory and returns a pointer 
> to that memory, does p/invoke free the memory once marshalling is complete?

It depends on the return type of the managed function.  Class types will
have the pointer freed through g_free (Mono) or CoTaskMemFree (.NET).
Struct types won't have the type automatically freed, so using IntPtr
won't let the runtime free your pointer.

 - Jon

More information about the Mono-list mailing list