Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <4205D6D1.70D38D40@dessent.net> Date: Sun, 06 Feb 2005 00:35:29 -0800 From: Brian Dessent Organization: My own little world... MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: gethostbyname() problem? References: <200502051240 DOT j15CevQ32345 AT webmail DOT web-mania DOT com> Content-Type: multipart/mixed; boundary="------------E35DB021543DD652983121CD" X-IsSubscribed: yes Reply-To: cygwin AT cygwin DOT com --------------E35DB021543DD652983121CD Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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 --------------E35DB021543DD652983121CD Content-Type: text/plain; charset=us-ascii; name="gethostbyname_sscanf.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="gethostbyname_sscanf.diff" 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)); --------------E35DB021543DD652983121CD Content-Type: text/plain; charset=us-ascii -- 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/ --------------E35DB021543DD652983121CD--