bug-guile
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Guile segfault with network calls


From: Gary Houston
Subject: Re: Guile segfault with network calls
Date: 3 Mar 2001 13:23:36 -0000

> From: Martin Grabmueller <address@hidden>
> Date: Thu, 1 Mar 2001 10:28:55 +0100 (MET)
> 
> Hello list,
> 
> Guile segfaults when a Unix domain address with a very long pathname is
> passed to calls like `connect', `bind' or `sendto'.
> 
> Example:
> 
> guile> (define s (socket AF_UNIX SOCK_STREAM 0))
> guile> (connect s AF_UNIX (make-string 100000 #\c))
> Segmentation fault
> 
> The reason is the following code in `scm_fill_sockaddr' in socket.c:424,
> where a memcpy is made without checking for the length.

Yikes, well spotted.

> #ifdef HAVE_UNIX_DOMAIN_SOCKETS
>     case AF_UNIX:
>       {
>       struct sockaddr_un *soka;
> 
>       soka = (struct sockaddr_un *)
>         scm_must_malloc (sizeof (struct sockaddr_un), proc);
>       memset (soka, 0, sizeof (struct sockaddr_un));
>       soka->sun_family = AF_UNIX;
>       SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
>       memcpy (soka->sun_path, SCM_STRING_CHARS (address),
>               1 + SCM_STRING_LENGTH (address));
>       *size = sizeof (struct sockaddr_un);
>       return (struct sockaddr *) soka;
>       }
> #endif
> 
> I don't know what the correct fix for this is, because I couldn't find
> out whether there is a standard maximum path length.  Maybe POSIX or
> one of the other `Standards' defines one?  Does anyone know?

We could use sizeof soka->sun_path.   But I noticed this comment in
the glibc manual:

    `char sun_path[108]'
          This is the file name to use.

          *Incomplete:*  Why is 108 a magic number?  RMS suggests making
          this a zero-length array and tweaking the following example
          to use `alloca' to allocate an appropriate amount of storage
          based on the length of the filename.

If it was implemented like that, sizeof wouldn't work.  How about this:

--- socket.c    2001/02/02 04:56:25     1.60
+++ socket.c    2001/03/03 13:19:32
@@ -425,15 +425,21 @@
     case AF_UNIX:
       {
        struct sockaddr_un *soka;
+       size_t addr_size;
 
+       SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
+       /* the static buffer size in sockaddr_un seems to be arbitrary
+          and not necessarily a hard limit.  let's ignore it.
+          sun_path is always the last member of the structure.  */
+       addr_size = sizeof (struct sockaddr_un)
+         + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
        soka = (struct sockaddr_un *)
-         scm_must_malloc (sizeof (struct sockaddr_un), proc);
-       memset (soka, 0, sizeof (struct sockaddr_un));
+         scm_must_malloc (addr_size, proc);
+       memset (soka, 0, addr_size);  /* for sun_len: see sin_len above. */
        soka->sun_family = AF_UNIX;
-       SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
        memcpy (soka->sun_path, SCM_STRING_CHARS (address),
-               1 + SCM_STRING_LENGTH (address));
-       *size = sizeof (struct sockaddr_un);
+               SCM_STRING_LENGTH (address) + 1);
+       *size = SUN_LEN (soka);
        return (struct sockaddr *) soka;
       }
 #endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]