Subject: Re: gethostbyname() problem?
From: Brian Dessent <[email-masked]>
To: [email-masked]
Date: Sun, 06 Feb 2005 00:35:29 -0800

HelpBytes wrote:

> The following code performs a lookup at a DNS block list,
> the DNS has an entry for this, and returns 127.0.0.2. In
> Linux using gcc, and in Windows using Visual Studio, this
> code works fine, and outputs 127.0.0.2.
> 
> However, in cygwin, it simply outputs 202.149.167.69., it seems
> no matter what is in the hostname, if it begins with what looks
> like an IP address, it returns it as the result.

Yes, it seems you are correct that there is a bug in Cygwin's
gethostbyname().  There is code in net.cc (cygwin_gethostbyname) to
attempt to detect if a literal dotted quad is passed and skip the name
lookup:

  if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
    {
      /* In case you don't have DNS, at least x.x.x.x still works */
      memset (&tmp, 0, sizeof (tmp));
      tmp_addr[0] = a;
      tmp_addr[1] = b;
      tmp_addr[2] = c;
      tmp_addr[3] = d;
      tmp_addr_list[0] = (char *) tmp_addr;
      tmp.h_name = name;
      tmp.h_aliases = tmp_aliases;
      tmp.h_addrtype = 2;
      tmp.h_length = 4;
      tmp.h_addr_list = tmp_addr_list;
      return &tmp;
    }

It seems that this code is flawed in that it does not check for whether
the sscanf matched the entire contents of `name' or whether it was a
partial match as in your testcase.

The attached patch adds the "%n" parameter to sscanf's format string
which is then used to determine if the amount of characters matched is
the same as the length of `name', which should avoid the false partial
match.  It seems to work correctly for me, but one of the actual Cygwin
developers will have to review it or fix it in some other way.

Brian

Index: src/winsup/cygwin/net.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/net.cc,v
retrieving revision 1.175
diff -u -p -r1.175 net.cc
--- src/winsup/cygwin/net.cc	19 Aug 2004 10:58:37 -0000	1.175
+++ src/winsup/cygwin/net.cc	6 Feb 2005 08:14:41 -0000
@@ -940,13 +940,13 @@ cygwin_gethostbyname (const char *name)
   static struct hostent tmp;
   static char *tmp_aliases[1];
   static char *tmp_addr_list[2];
-  static int a, b, c, d;
+  static int a, b, c, d, n;
 
   sig_dispatch_pending ();
   if (check_null_str_errno (name))
     return NULL;
 
-  if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
+  if (sscanf (name, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4 && (unsigned)n == strlen (name))
     {
       /* In case you don't have DNS, at least x.x.x.x still works */
       memset (&tmp, 0, sizeof (tmp));

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/