ws2_32: Fix hostent memory allocation.

This commit is contained in:
Bruno Jesus 2012-06-09 14:34:59 -03:00 committed by Alexandre Julliard
parent 524a817195
commit b2af5e1d31
2 changed files with 46 additions and 37 deletions

View File

@ -326,7 +326,7 @@ static INT num_startup; /* reference counter */
static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook; static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* function prototypes */ /* function prototypes */
static struct WS_hostent *WS_create_he(char *name, int aliases, int addresses, int fill_addresses); static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length);
static struct WS_hostent *WS_dup_he(const struct hostent* p_he); static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe); static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
static struct WS_servent *WS_dup_se(const struct servent* p_se); static struct WS_servent *WS_dup_se(const struct servent* p_se);
@ -4557,7 +4557,7 @@ static struct WS_hostent* WS_get_local_ips( char *hostname )
/* Allocate a hostent and enough memory for all the IPs, /* Allocate a hostent and enough memory for all the IPs,
* including the NULL at the end of the list. * including the NULL at the end of the list.
*/ */
hostlist = WS_create_he(hostname, 1, numroutes+1, TRUE); hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
if (hostlist == NULL) if (hostlist == NULL)
goto cleanup; /* Failed to allocate a hostent for the list of IPs */ goto cleanup; /* Failed to allocate a hostent for the list of IPs */
hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */ hostlist->h_addr_list[numroutes] = NULL; /* NULL-terminate the address list */
@ -5581,54 +5581,51 @@ static int list_dup(char** l_src, char** l_to, int item_size)
* *
* Creates the entry with enough memory for the name, aliases * Creates the entry with enough memory for the name, aliases
* addresses, and the address pointers. Also copies the name * addresses, and the address pointers. Also copies the name
* and sets up all the pointers. If "fill_addresses" is set then * and sets up all the pointers.
* sufficient memory for the addresses is also allocated and the
* address pointers are set to this memory.
* *
* NOTE: The alias and address lists must be allocated with room * NOTE: The alias and address lists must be allocated with room
* for the NULL item terminating the list. This is true even if * for the NULL item terminating the list. This is true even if
* the list has no items ("aliases" and "addresses" must be * the list has no items ("aliases" and "addresses" must be
* at least "1", a truly empty list is invalid). * at least "1", a truly empty list is invalid).
*/ */
static struct WS_hostent *WS_create_he(char *name, int aliases, int addresses, int fill_addresses) static struct WS_hostent *WS_create_he(char *name, int aliases, int aliases_size, int addresses, int address_length)
{ {
struct WS_hostent *p_to; struct WS_hostent *p_to;
char *p; char *p;
int size = (sizeof(struct WS_hostent) + int size = (sizeof(struct WS_hostent) +
strlen(name) + 1 + strlen(name) + 1 +
sizeof(char *)*aliases + sizeof(char *) * aliases +
sizeof(char *)*addresses); aliases_size +
sizeof(char *) * addresses +
/* Allocate enough memory for the addresses */ address_length * (addresses - 1)), i;
if (fill_addresses)
size += sizeof(struct in_addr)*addresses;
if (!(p_to = check_buffer_he(size))) return NULL; if (!(p_to = check_buffer_he(size))) return NULL;
memset(p_to, 0, size); memset(p_to, 0, size);
/* Use the memory in the same way winsock does.
* First set the pointer for aliases, second set the pointers for addressess.
* Third fill the addresses indexes, fourth jump aliases names size.
* Fifth fill the hostname.
* NOTE: This method is valid for OS version's >= XP.
*/
p = (char *)(p_to + 1); p = (char *)(p_to + 1);
p_to->h_name = p;
strcpy(p, name);
p += strlen(p) + 1;
p_to->h_aliases = (char **)p; p_to->h_aliases = (char **)p;
p += sizeof(char *)*aliases; p += sizeof(char *)*aliases;
p_to->h_addr_list = (char **)p; p_to->h_addr_list = (char **)p;
p += sizeof(char *)*addresses; p += sizeof(char *)*addresses;
if (fill_addresses)
{
int i;
/* NOTE: h_aliases must be filled in manually, leave these for (i = 0, addresses--; i < addresses; i++, p += address_length)
* pointers NULL (already set to NULL by memset earlier). p_to->h_addr_list[i] = p;
/* NOTE: h_aliases must be filled in manually because we don't know each string
* size, leave these pointers NULL (already set to NULL by memset earlier).
*/ */
p += aliases_size;
p_to->h_name = p;
strcpy(p, name);
/* Fill in the list of address pointers */
for (i = 0; i < addresses; i++)
p_to->h_addr_list[i] = (p += sizeof(struct in_addr));
p += sizeof(struct in_addr);
}
return p_to; return p_to;
} }
@ -5638,18 +5635,30 @@ static struct WS_hostent *WS_create_he(char *name, int aliases, int addresses, i
*/ */
static struct WS_hostent *WS_dup_he(const struct hostent* p_he) static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
{ {
int addresses = list_size(p_he->h_addr_list, p_he->h_length); int i, addresses = 0, alias_size = 0;
int aliases = list_size(p_he->h_aliases, 0);
struct WS_hostent *p_to; struct WS_hostent *p_to;
char *p;
p_to = WS_create_he(p_he->h_name, aliases, addresses, FALSE); for( i = 0; p_he->h_aliases[i]; i++) alias_size += strlen(p_he->h_aliases[i]) + 1;
while (p_he->h_addr_list[addresses]) addresses++;
p_to = WS_create_he(p_he->h_name, i + 1, alias_size, addresses + 1, p_he->h_length);
if (!p_to) return NULL; if (!p_to) return NULL;
p_to->h_addrtype = p_he->h_addrtype; p_to->h_addrtype = p_he->h_addrtype;
p_to->h_length = p_he->h_length; p_to->h_length = p_he->h_length;
list_dup(p_he->h_aliases, p_to->h_aliases, 0); for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->h_length)
list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length); memcpy(p, p_he->h_addr_list[i], p_to->h_length);
/* Fill the aliases after the IP data */
for(i = 0; p_he->h_aliases[i]; i++)
{
p_to->h_aliases[i] = p;
strcpy(p, p_he->h_aliases[i]);
p += strlen(p) + 1;
}
return p_to; return p_to;
} }

View File

@ -2759,22 +2759,22 @@ static void test_dns(void)
addr.mem = h + 1; addr.mem = h + 1;
if(h->h_addr_list == addr.mem) /* <= W2K */ if(h->h_addr_list == addr.mem) /* <= W2K */
{ {
skip("Skipping hostent tests since this OS is unsupported\n"); win_skip("Skipping hostent tests since this OS is unsupported\n");
return; return;
} }
todo_wine ok(h->h_aliases == addr.mem, ok(h->h_aliases == addr.mem,
"hostent->h_aliases should be in %p, it is in %p\n", addr.mem, h->h_aliases); "hostent->h_aliases should be in %p, it is in %p\n", addr.mem, h->h_aliases);
for(ptr = h->h_aliases, acount = 1; *ptr; ptr++) acount++; for(ptr = h->h_aliases, acount = 1; *ptr; ptr++) acount++;
addr.chr += sizeof(*ptr) * acount; addr.chr += sizeof(*ptr) * acount;
todo_wine ok(h->h_addr_list == addr.mem, ok(h->h_addr_list == addr.mem,
"hostent->h_addr_list should be in %p, it is in %p\n", addr.mem, h->h_addr_list); "hostent->h_addr_list should be in %p, it is in %p\n", addr.mem, h->h_addr_list);
for(ptr = h->h_addr_list, acount = 1; *ptr; ptr++) acount++; for(ptr = h->h_addr_list, acount = 1; *ptr; ptr++) acount++;
addr.chr += sizeof(*ptr) * acount; addr.chr += sizeof(*ptr) * acount;
todo_wine ok(h->h_addr_list[0] == addr.mem, ok(h->h_addr_list[0] == addr.mem,
"hostent->h_addr_list[0] should be in %p, it is in %p\n", addr.mem, h->h_addr_list[0]); "hostent->h_addr_list[0] should be in %p, it is in %p\n", addr.mem, h->h_addr_list[0]);
} }