[#3006] CVS repository — "Eugene Scripnik" <hoaz@...>

Hello.

21 messages 2004/06/16
[#3008] Re: CVS repository — ts <decoux@...> 2004/06/16

>>>>> "E" == Eugene Scripnik <hoaz@gala.net> writes:

[#3009] Re: CVS repository — Michal Rokos <michal@...> 2004/06/16

Hi!

[#3057] Ruby 1.8.2 to be released. — matz@... (Yukihiro Matsumoto)

Hi,

20 messages 2004/06/23

I think I found the recvfrom problem!!

From: Dave Thomas <dave@...>
Date: 2004-06-22 19:44:58 UTC
List: ruby-core #3043
I think there's a bug in socket.c's recvfrom implementation.

Some background.  Folks on Mac OS X must disable reverse lookups before 
using most socket stuff. If we don't, we get the error

    in `recvfrom': getnameinfo: Non-recoverable failure in name 
resolution (SocketError)

I think I've tracked this down.

The Ruby recvfrom() method returns an assoc containing the data and the 
IPAddr of the sender of the data. This code looks something like:

    slen = recvfrom(fd, RSTRING(str)->ptr, buflen, flags, (struct 
sockaddr*)buf, &alen);
    ....
     switch (from) {
       ...
       case RECV_IP:
	  return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, fptr->mode & 
FMODE_NOREVLOOKUP));
          ...
     }

The 'buf' parameter is the sockaddr returned by the low-level 
recvfrom(2) call.

However... the man page for recvfrom on a BSD box says (among other 
things)

      If from is non-nil, and the socket is not connection-oriented, the 
source
      address of the message is filled in.  Fromlen is a value-result 
parame-
      ter, initialized to the size of the buffer associated with from, 
and mod-
      ified on return to indicate the actual size of the address stored 
there.

Note: it only fills the data in if the socket is not connection 
oriented. TCP sockets are connection oriented, so the alen parameter 
was being set to '0' and the buf parameter contained random data. This 
was being used in a reverse lookup, and failing.

I propose the following patch: if the recvfrom (2) call does not return 
a sockaddr (ie, if alen is zero), then the Ruby recvfrom call returns

      [ data, nil ]

otherwise, it returns

    [ data,  IPAddr... ]

Here's a diff for the change: I've tried it here on some simple 
programs and it seems to work OK, but I don't know if there will be  
other implications from the nil value. Either way, there's a definite 
bug here.


Index: ext/socket/socket.c
===================================================================
RCS file: /var/cvs/src/ruby/ext/socket/socket.c,v
retrieving revision 1.124
diff -u -r1.124 socket.c
--- ext/socket/socket.c 20 May 2004 06:04:39 -0000      1.124
+++ ext/socket/socket.c 22 Jun 2004 19:33:24 -0000
@@ -492,7 +492,11 @@
             rb_raise(rb_eTypeError, "sockaddr size differs - should not 
happen");
         }
  #endif
-       return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, 
fptr->mode & FMODE_NOREVLOOKUP));
+       if (alen)
+         return rb_assoc_new(str, ipaddr((struct sockaddr*)buf, 
fptr->mode & FMODE_NOREVLOOKUP));
+       else
+         return rb_assoc_new(str, Qnil);
+
  #ifdef HAVE_SYS_UN_H
        case RECV_UNIX:
         return rb_assoc_new(str, unixaddr((struct sockaddr_un*)buf));


Cheers

Dave


In This Thread

Prev Next