Module: wine Branch: master Commit: b2af5e1d311d409e725c67c731bf83c9fd8fdea6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b2af5e1d311d409e725c67c731...
Author: Bruno Jesus 00cpxxx@gmail.com Date: Sat Jun 9 14:34:59 2012 -0300
ws2_32: Fix hostent memory allocation.
---
dlls/ws2_32/socket.c | 75 +++++++++++++++++++++++++-------------------- dlls/ws2_32/tests/sock.c | 8 ++-- 2 files changed, 46 insertions(+), 37 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index fd19ab2..b2bed09 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -326,7 +326,7 @@ static INT num_startup; /* reference counter */ static FARPROC blocking_hook = (FARPROC)WSA_DefaultBlockingHook;
/* 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_protoent *WS_dup_pe(const struct protoent* p_pe); 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, * 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) goto cleanup; /* Failed to allocate a hostent for the list of IPs */ 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 * addresses, and the address pointers. Also copies the name - * and sets up all the pointers. If "fill_addresses" is set then - * sufficient memory for the addresses is also allocated and the - * address pointers are set to this memory. + * and sets up all the pointers. * * NOTE: The alias and address lists must be allocated with room * for the NULL item terminating the list. This is true even if * the list has no items ("aliases" and "addresses" must be * 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; char *p; - int size = (sizeof(struct WS_hostent) + strlen(name) + 1 + - sizeof(char *)*aliases + - sizeof(char *)*addresses); - - /* Allocate enough memory for the addresses */ - if (fill_addresses) - size += sizeof(struct in_addr)*addresses; + sizeof(char *) * aliases + + aliases_size + + sizeof(char *) * addresses + + address_length * (addresses - 1)), i;
if (!(p_to = check_buffer_he(size))) return NULL; 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_to->h_name = p; - strcpy(p, name); - p += strlen(p) + 1; - p_to->h_aliases = (char **)p; p += sizeof(char *)*aliases; + p_to->h_addr_list = (char **)p; p += sizeof(char *)*addresses; - if (fill_addresses) - { - int i;
- /* NOTE: h_aliases must be filled in manually, leave these - * pointers NULL (already set to NULL by memset earlier). - */ + for (i = 0, addresses--; i < addresses; i++, p += address_length) + 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; }
@@ -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) { - int addresses = list_size(p_he->h_addr_list, p_he->h_length); - int aliases = list_size(p_he->h_aliases, 0); + int i, addresses = 0, alias_size = 0; 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; p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
- list_dup(p_he->h_aliases, p_to->h_aliases, 0); - list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length); + for(i = 0, p = p_to->h_addr_list[0]; p_he->h_addr_list[i]; i++, p += p_to->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; }
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 85d126b..2543873 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -2759,22 +2759,22 @@ static void test_dns(void) addr.mem = h + 1; 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; }
- 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);
for(ptr = h->h_aliases, acount = 1; *ptr; 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);
for(ptr = h->h_addr_list, acount = 1; *ptr; 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]); }