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