Bruno Jesus : ws2_32: Fix hostent memory allocation.
Alexandre Julliard
julliard at winehq.org
Tue Jun 12 13:36:31 CDT 2012
Module: wine
Branch: master
Commit: b2af5e1d311d409e725c67c731bf83c9fd8fdea6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b2af5e1d311d409e725c67c731bf83c9fd8fdea6
Author: Bruno Jesus <00cpxxx at 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]);
}
More information about the wine-cvs
mailing list