From 5a4a30b9b5747c4ed9a1e70b75c269b81d16972a Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Mon, 26 Jun 2006 03:13:48 +0000 Subject: [PATCH] pull up r18180:18182 from trunk r18180@cathode-dark-space: raeburn | 2006-06-20 19:59:11 -0400 ticket: new subject: getaddrinfo code uses vars outside of storage duration The calls to gethostbyname_r and friends were wrapped in macros that declared automatic variables for the auxiliary storage needed, but the pointers returned by the functions would be used outside of that scope, when the storage would no longer be valid. Changed the macro interfaces to define new types for the auxiliary storage, and add a new argument to the macros referring to that storage. Changed call sites accordingly. r18181@cathode-dark-space: raeburn | 2006-06-20 19:59:56 -0400 ticket: 18180 Revert an untested change that wasn't supposed to go into this ticket. r18182@cathode-dark-space: raeburn | 2006-06-20 20:12:03 -0400 ticket: 3911 Revert part of previous changes: Move temporary values that don't need longer storage duration, like error codes, back into GET_*_BY_* macros. ticket: 3911 version_fixed: 1.5 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-5@18225 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/support/fake-addrinfo.c | 148 +++++++++++++++++-------------- 1 file changed, 82 insertions(+), 66 deletions(-) diff --git a/src/util/support/fake-addrinfo.c b/src/util/support/fake-addrinfo.c index 922dc8d9b..a622302b8 100644 --- a/src/util/support/fake-addrinfo.c +++ b/src/util/support/fake-addrinfo.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001,2002,2003,2004,2005 by the Massachusetts Institute of Technology, + * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology, * Cambridge, MA, USA. All Rights Reserved. * * This software is being provided to you, the LICENSEE, by the @@ -162,20 +162,23 @@ extern /*@dependent@*/ char *gai_strerror (int code) /*@*/; either getaddrinfo or one of these two flavors of gethostbyname_r? */ #if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME) -#define GET_HOST_BY_NAME(NAME, HP, ERR) \ - { (HP) = gethostbyname (NAME); (ERR) = h_errno; } -#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \ - { (HP) = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; } +typedef struct hostent *GET_HOST_TMP; +#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ + { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; } +#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \ + { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; } #else #ifdef _AIX /* XXX should have a feature test! */ -#define GET_HOST_BY_NAME(NAME, HP, ERR) \ - { \ - struct hostent my_h_ent; \ - struct hostent_data my_h_ent_data; \ - (HP) = (gethostbyname_r((NAME), &my_h_ent, &my_h_ent_data) \ - ? 0 \ - : &my_h_ent); \ - (ERR) = h_errno; \ +typedef struct { + struct hostent ent; + struct hostent_data data; +} GET_HOST_TMP; +#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ + { \ + (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \ + ? 0 \ + : &my_h_ent); \ + (ERR) = h_errno; \ } /* #define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \ @@ -191,47 +194,49 @@ extern /*@dependent@*/ char *gai_strerror (int code) /*@*/; */ #else #ifdef GETHOSTBYNAME_R_RETURNS_INT -#define GET_HOST_BY_NAME(NAME, HP, ERR) \ +typedef struct { + struct hostent ent; + char buf[8192]; +} GET_HOST_TMP; +#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ { \ - struct hostent my_h_ent, *my_hp; \ + struct hostent *my_hp; \ int my_h_err; \ - char my_h_buf[8192]; \ - (HP) = (gethostbyname_r((NAME), &my_h_ent, \ - my_h_buf, sizeof (my_h_buf), &my_hp, \ + (HP) = (gethostbyname_r((NAME), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &TMP.hp, \ &my_h_err) \ ? 0 \ - : &my_h_ent); \ + : &TMP.ent); \ (ERR) = my_h_err; \ } -#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \ +#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \ { \ - struct hostent my_h_ent, *my_hp; \ + struct hostent *my_hp; \ int my_h_err; \ - char my_h_buf[8192]; \ - (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \ - my_h_buf, sizeof (my_h_buf), &my_hp, \ + (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &my_hp, \ &my_h_err) \ ? 0 \ - : &my_h_ent); \ + : &TMP.ent); \ (ERR) = my_h_err; \ } #else -#define GET_HOST_BY_NAME(NAME, HP, ERR) \ +typedef struct { + struct hostent ent; + char buf[8192]; +} GET_HOST_TMP; +#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \ { \ - struct hostent my_h_ent; \ int my_h_err; \ - char my_h_buf[8192]; \ - (HP) = gethostbyname_r((NAME), &my_h_ent, \ - my_h_buf, sizeof (my_h_buf), &my_h_err); \ + (HP) = gethostbyname_r((NAME), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &my_h_err); \ (ERR) = my_h_err; \ } -#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \ +#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \ { \ - struct hostent my_h_ent; \ int my_h_err; \ - char my_h_buf[8192]; \ - (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \ - my_h_buf, sizeof (my_h_buf), &my_h_err); \ + (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &my_h_err); \ (ERR) = my_h_err; \ } #endif /* returns int? */ @@ -240,53 +245,57 @@ extern /*@dependent@*/ char *gai_strerror (int code) /*@*/; /* Now do the same for getservby* functions. */ #ifndef HAVE_GETSERVBYNAME_R -#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \ - ((SP) = getservbyname (NAME, PROTO), (ERR) = (SP) ? 0 : -1) -#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \ - ((SP) = getservbyport (PORT, PROTO), (ERR) = (SP) ? 0 : -1) +typedef struct servent *GET_SERV_TMP; +#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \ + (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1) +#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \ + (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1) #else #ifdef GETSERVBYNAME_R_RETURNS_INT -#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \ +typedef struct { + struct servent ent; + char buf[8192]; +} GET_SERV_TMP; +#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \ { \ - struct servent my_s_ent, *my_sp; \ + struct servent *my_sp; \ int my_s_err; \ - char my_s_buf[8192]; \ - (SP) = (getservbyname_r((NAME), (PROTO), &my_s_ent, \ - my_s_buf, sizeof (my_s_buf), &my_sp, \ + (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &my_sp, \ &my_s_err) \ ? 0 \ - : &my_s_ent); \ + : &TMP.ent); \ (ERR) = my_s_err; \ } -#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \ +#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \ { \ - struct servent my_s_ent, *my_sp; \ + struct servent *my_sp; \ int my_s_err; \ - char my_s_buf[8192]; \ - (SP) = (getservbyport_r((PORT), (PROTO), &my_s_ent, \ - my_s_buf, sizeof (my_s_buf), &my_sp, \ + (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf), &my_sp, \ &my_s_err) \ ? 0 \ - : &my_s_ent); \ + : &TMP.ent); \ (ERR) = my_s_err; \ } #else /* returns ptr -- IRIX? */ -#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \ +typedef struct { + struct servent ent; + char buf[8192]; +} GET_SERV_TMP; +#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \ { \ - struct servent my_s_ent; \ - char my_s_buf[8192]; \ - (SP) = getservbyname_r((NAME), (PROTO), &my_s_ent, \ - my_s_buf, sizeof (my_s_buf)); \ + (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf)); \ (ERR) = (SP) == NULL; \ } -#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \ +#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \ { \ - struct servent my_s_ent, *my_sp; \ - char my_s_buf[8192]; \ - my_sp = getservbyport_r((PORT), (PROTO), &my_s_ent, \ - my_s_buf, sizeof (my_s_buf)); \ + struct servent *my_sp; \ + my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \ + TMP.buf, sizeof (TMP.buf)); \ (SP) = my_sp; \ (ERR) = my_sp == 0; \ (ERR) = (ERR); /* avoid "unused" warning */ \ @@ -774,8 +783,9 @@ static inline int fai_add_hosts_by_name (const char *name, struct hostent *hp; int i, r; int herr; + GET_HOST_TMP htmp; - GET_HOST_BY_NAME (name, hp, herr); + GET_HOST_BY_NAME (name, hp, herr, htmp); if (hp == 0) return translate_h_errno (herr); for (i = 0; hp->h_addr_list[i]; i++) { @@ -840,6 +850,7 @@ fake_getaddrinfo (const char *name, const char *serv, } else { struct servent *sp; int try_dgram_too = 0, s_err; + GET_SERV_TMP stmp; if (socktype == 0) { try_dgram_too = 1; @@ -847,7 +858,7 @@ fake_getaddrinfo (const char *name, const char *serv, } try_service_lookup: GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp", - sp, s_err); + sp, s_err, stmp); if (sp == 0) { if (try_dgram_too) { socktype = SOCK_DGRAM; @@ -952,9 +963,11 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, #endif } else { int herr; + GET_HOST_TMP htmp; + GET_HOST_BY_ADDR((const char *) &sinp->sin_addr, sizeof (struct in_addr), - sa->sa_family, hp, herr); + sa->sa_family, hp, herr, htmp); if (hp == 0) { if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */ goto numeric_host; @@ -980,9 +993,11 @@ fake_getnameinfo (const struct sockaddr *sa, socklen_t len, strncpy (service, numbuf, slen); } else { int serr; + GET_SERV_TMP stmp; + GET_SERV_BY_PORT(sinp->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp", - sp, serr); + sp, serr, stmp); if (sp == 0) goto numeric_service; strncpy (service, sp->s_name, slen); @@ -1185,13 +1200,14 @@ getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint, struct hostent *hp; const char *name2 = 0; int i, herr; + GET_HOST_TMP htmp; /* * Current versions of GET_HOST_BY_NAME will fail if the * target hostname has IPv6 addresses only. Make sure it * fails fairly cleanly. */ - GET_HOST_BY_NAME (name, hp, herr); + GET_HOST_BY_NAME (name, hp, herr, htmp); if (hp == 0) { /* * This case probably means it's an IPv6-only name. If -- 2.26.2