This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

gethostbyname_r broken



The program below tests gethostbyname_r with an unknown host.  The
function returns with 0 (instead of != 0) but doesn't set the host
pointer:

$ ./gethst_r-test 
gethostbyname_r returned: 0
herr: 1
hp is null

nss/getXXbyYY_r.c now has:
  return status == NSS_STATUS_SUCCESS ? 0 : errno;

But what happens if errno is 0 and status != NSS_STATUS_SUCCESS (this
happens with host not found in my test program)?  Before Ulrich's
change we always returned -1 and could easily check for it.  The glibc
manual isn't clear on this - do I have to check also the return
pointer for NULL if the result is 0?  The POSIX documentation seems to 
imply this.

Let's look at an example from glibc (inet/rcmd.c):
	while (__gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen,
				  &hp, &herr) != 0)
	  if (herr != NETDB_INTERNAL || errno != ERANGE)
	    {
	      __set_h_errno (herr);
	      herror(*ahost);
	      return -1;
	    }
	  else
	    {
	      /* Enlarge the buffer.  */
	      hstbuflen *= 2;
	      tmphstbuf = __alloca (hstbuflen);
	    }
	pfd[0].events = POLLIN;
	pfd[1].events = POLLIN;

	*ahost = hp->h_name;

This code segfaults accessing hp->h_name iff the host doesn't exist.

We need to add at least the following code after the loop:
	if (hp == NULL)
	  {
	    __set_h_errno (herr);
	    herror(*ahost);
	    return -1;
	  }

I'm appending a patch for inet/rcmd.c which fixes one of the three
gethostbyname_r calls and like to get your comments on it before I fix 
the rest.

Andreas


#include <netdb.h>
#include <stdio.h>
#include <alloca.h>

int
main (void)
{
  struct hostent hostbuf, *hp;
  size_t hstbuflen;
  char *tmphstbuf;
  int res;
  int herr;
  
  hstbuflen = 1024;
  tmphstbuf = alloca (hstbuflen);

  res = gethostbyname_r ("unknownhost", &hostbuf, tmphstbuf, hstbuflen, &hp, &herr);

  printf ("gethostbyname_r returned: %d\n", res);
  printf ("herr: %d\n", herr);
  printf ("hp is %s\n", hp == NULL ? "null" : "set");

  return res;
}


--- inet/rcmd.c.~2~	Mon Jun 28 22:36:37 1999
+++ inet/rcmd.c	Tue Jun 29 08:21:23 1999
@@ -79,21 +79,22 @@
 
 	hstbuflen = 1024;
 	tmphstbuf = __alloca (hstbuflen);
-	while (__gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen,
-				  &hp, &herr) != 0)
-	  if (herr != NETDB_INTERNAL || errno != ERANGE)
-	    {
-	      __set_h_errno (herr);
-	      herror(*ahost);
-	      return -1;
-	    }
-	  else
-	    {
-	      /* Enlarge the buffer.  */
-	      hstbuflen *= 2;
-	      tmphstbuf = __alloca (hstbuflen);
-	    }
-
+	
+	while ((__gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen,
+				   &hp, &herr) != 0) &&
+	       (herr == NETDB_INTERNAL) && (errno == ERANGE))
+	  {
+	    /* Enlarge the buffer.  */
+	    hstbuflen *= 2;
+	    tmphstbuf = __alloca (hstbuflen);
+	  }
+	if (herr != 0 || hp == NULL)
+	  {
+	    __set_h_errno (herr);
+	    herror(*ahost);
+	    return -1;
+	  }
+	
 	pfd[0].events = POLLIN;
 	pfd[1].events = POLLIN;
 

-- 
 Andreas Jaeger   aj@arthur.rhein-neckar.de    jaeger@informatik.uni-kl.de
  for pgp-key finger ajaeger@aixd1.rhrk.uni-kl.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]