diff options
Diffstat (limited to 'nis')
-rw-r--r-- | nis/nss_nis/nis-hosts.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c index 24d13634d7..8accf53edf 100644 --- a/nis/nss_nis/nis-hosts.c +++ b/nis/nss_nis/nis-hosts.c @@ -485,24 +485,6 @@ _nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, return retval; } - struct parser_data data; - struct hostent host; - int parse_res = parse_line (result, &host, &data, buflen, errnop, AF_UNSPEC, - 0); - if (__builtin_expect (parse_res < 1, 0)) - { - if (parse_res == -1) - { - *herrnop = NETDB_INTERNAL; - return NSS_STATUS_TRYAGAIN; - } - else - { - *herrnop = HOST_NOT_FOUND; - return NSS_STATUS_NOTFOUND; - } - } - if (*pat == NULL) { uintptr_t pad = (-(uintptr_t) buffer @@ -524,16 +506,48 @@ _nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, buflen -= sizeof (struct gaih_addrtuple); } - (*pat)->next = NULL; - size_t h_name_len = strlen (host.h_name); - if (h_name_len >= buflen) + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data); + buffer += pad; + + struct parser_data *data = (void *) buffer; + + if (__builtin_expect (buflen < sizeof *data + 1 + pad, 0)) goto erange; - (*pat)->name = memcpy (buffer, host.h_name, h_name_len + 1); + buflen -= pad; + + struct hostent host; + int parse_res = parse_line (result, &host, data, buflen, errnop, AF_UNSPEC, + 0); + if (__builtin_expect (parse_res < 1, 0)) + { + if (parse_res == -1) + { + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + else + { + *herrnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + } + + (*pat)->next = NULL; (*pat)->family = host.h_addrtype; memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length); (*pat)->scopeid = 0; assert (host.h_addr_list[1] == NULL); + /* Undo the alignment for parser_data. */ + buffer -= pad; + buflen += pad; + + size_t h_name_len = strlen (host.h_name) + 1; + if (h_name_len >= buflen) + goto erange; + /* Potentially the string and the destination buffer overlap. */ + (*pat)->name = memmove (buffer, host.h_name, h_name_len); + free (result); return NSS_STATUS_SUCCESS; |