ws2_32: Fix conversion of address in GetAddrInfoW
Bruno Jesus
00cpxxx at gmail.com
Mon Feb 17 20:56:03 CST 2014
While creating additional tests to help patch 102499 [1] get commited
I found a problem in the conversion between ai_addr from A to W. The
problem is that the current implementation uses the
sizeof(WS_sockaddr) regardless of the real address size which is in
ai_addrlen.
This patch fixes that and also ensures that patch [1] is correct by
comparing all fields from the addresses returned by calling
getaddrinfo with "" and "0" service name.
[1] http://source.winehq.org/patches/data/102499
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index a9ac79d..2a2c809 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -5612,13 +5612,13 @@ static struct WS_addrinfoW *addrinfo_AtoW(const struct WS_addrinfo *ai)
}
if (ai->ai_addr)
{
- if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(struct WS_sockaddr))))
+ if (!(ret->ai_addr = HeapAlloc(GetProcessHeap(), 0, ai->ai_addrlen)))
{
HeapFree(GetProcessHeap(), 0, ret->ai_canonname);
HeapFree(GetProcessHeap(), 0, ret);
return NULL;
}
- memcpy(ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr));
+ memcpy(ret->ai_addr, ai->ai_addr, ai->ai_addrlen);
}
return ret;
}
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index e146548..09e8d29 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -349,6 +349,66 @@ static void check_so_opentype (void)
ok ( tmp == 0, "check_so_opentype: wrong startup value of SO_OPENTYPE: %d\n", tmp );
}
+static void compare_addrinfo (ADDRINFO *a, ADDRINFO *b)
+{
+ for (; a && b ; a = a->ai_next, b = b->ai_next)
+ {
+ ok(a->ai_flags == b->ai_flags,
+ "Wrong flags %d != %d\n", a->ai_flags, b->ai_flags);
+ ok(a->ai_family == b->ai_family,
+ "Wrong family %d != %d\n", a->ai_family, b->ai_family);
+ ok(a->ai_socktype == b->ai_socktype,
+ "Wrong socktype %d != %d\n", a->ai_socktype, b->ai_socktype);
+ ok(a->ai_protocol == b->ai_protocol,
+ "Wrong protocol %d != %d\n", a->ai_protocol, b->ai_protocol);
+ ok(a->ai_addrlen == b->ai_addrlen,
+ "Wrong addrlen %lu != %lu\n", a->ai_addrlen, b->ai_addrlen);
+ ok(!memcmp(a->ai_addr, b->ai_addr, min(a->ai_addrlen, b->ai_addrlen)),
+ "Wrong address data\n");
+ if (a->ai_canonname && b->ai_canonname)
+ {
+ ok(!strcmp(a->ai_canonname, b->ai_canonname),
+ "Wrong canonical name '%s' != '%s'\n", a->ai_canonname, b->ai_canonname);
+ }
+ else if(a->ai_canonname || b->ai_canonname)
+ ok(0, "Expected both canonical names present (%p != %p)\n", a->ai_canonname, b->ai_canonname);
+ }
+ if (a || b)
+ ok(0, "Expected both addresses null (%p != %p)\n", a, b);
+}
+
+static void compare_addrinfow (ADDRINFOW *a, ADDRINFOW *b)
+{
+ for (; a && b ; a = a->ai_next, b = b->ai_next)
+ {
+ ok(a->ai_flags == b->ai_flags,
+ "Wrong flags %d != %d\n", a->ai_flags, b->ai_flags);
+ ok(a->ai_family == b->ai_family,
+ "Wrong family %d != %d\n", a->ai_family, b->ai_family);
+ ok(a->ai_socktype == b->ai_socktype,
+ "Wrong socktype %d != %d\n", a->ai_socktype, b->ai_socktype);
+ ok(a->ai_protocol == b->ai_protocol,
+ "Wrong protocol %d != %d\n", a->ai_protocol, b->ai_protocol);
+ ok(a->ai_addrlen == b->ai_addrlen,
+ "Wrong addrlen %lu != %lu\n", a->ai_addrlen, b->ai_addrlen);
+ ok(!memcmp(a->ai_addr, b->ai_addr, min(a->ai_addrlen, b->ai_addrlen)),
+ "Wrong address data\n");
+ if (a->ai_canonname && b->ai_canonname)
+ {
+ char bufa[128], bufb[128];
+ WideCharToMultiByte(CP_ACP, 0, a->ai_canonname, -1,
+ bufa, sizeof(bufa), NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, b->ai_canonname, -1,
+ bufb, sizeof(bufb), NULL, NULL);
+ ok(!strcmp(bufa, bufb), "Wrong canonical name '%s' != '%s'\n", bufa, bufb);
+ }
+ else if(a->ai_canonname || b->ai_canonname)
+ ok(0, "Expected both canonical names present (%p != %p)\n", a->ai_canonname, b->ai_canonname);
+ }
+ if (a || b)
+ ok(0, "Expected both addresses null (%p != %p)\n", a, b);
+}
+
/**************** Server utility functions ***************/
/*
@@ -5375,7 +5435,7 @@ static void test_GetAddrInfoW(void)
{'n','x','d','o','m','a','i','n','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
static const WCHAR zero[] = {'0',0};
int i, ret;
- ADDRINFOW *result, *p, hint;
+ ADDRINFOW *result, *result2, *p, hint;
if (!pGetAddrInfoW || !pFreeAddrInfoW)
{
@@ -5399,25 +5459,27 @@ static void test_GetAddrInfoW(void)
ret = pGetAddrInfoW(NULL, zero, NULL, &result);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
ok(result != NULL, "GetAddrInfoW failed\n");
- pFreeAddrInfoW(result);
- result = NULL;
- ret = pGetAddrInfoW(NULL, empty, NULL, &result);
+ result2 = NULL;
+ ret = pGetAddrInfoW(NULL, empty, NULL, &result2);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
- ok(result != NULL, "GetAddrInfoW failed\n");
+ ok(result2 != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfow(result, result2);
pFreeAddrInfoW(result);
+ pFreeAddrInfoW(result2);
result = NULL;
ret = pGetAddrInfoW(empty, zero, NULL, &result);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
ok(result != NULL, "GetAddrInfoW failed\n");
- pFreeAddrInfoW(result);
- result = NULL;
- ret = pGetAddrInfoW(empty, empty, NULL, &result);
+ result2 = NULL;
+ ret = pGetAddrInfoW(empty, empty, NULL, &result2);
ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
- ok(result != NULL, "GetAddrInfoW failed\n");
+ ok(result2 != NULL, "GetAddrInfoW failed\n");
+ compare_addrinfow(result, result2);
pFreeAddrInfoW(result);
+ pFreeAddrInfoW(result2);
result = NULL;
ret = pGetAddrInfoW(localhost, NULL, NULL, &result);
@@ -5514,7 +5576,7 @@ static void test_GetAddrInfoW(void)
static void test_getaddrinfo(void)
{
int i, ret;
- ADDRINFOA *result, *p, hint;
+ ADDRINFOA *result, *result2, *p, hint;
if (!pgetaddrinfo || !pfreeaddrinfo)
{
@@ -5538,25 +5600,27 @@ static void test_getaddrinfo(void)
ret = pgetaddrinfo(NULL, "0", NULL, &result);
ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
ok(result != NULL, "getaddrinfo failed\n");
- pfreeaddrinfo(result);
- result = NULL;
- ret = pgetaddrinfo(NULL, "", NULL, &result);
+ result2 = NULL;
+ ret = pgetaddrinfo(NULL, "", NULL, &result2);
ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
- ok(result != NULL, "getaddrinfo failed\n");
+ ok(result2 != NULL, "getaddrinfo failed\n");
+ compare_addrinfo(result, result2);
pfreeaddrinfo(result);
+ pfreeaddrinfo(result2);
result = NULL;
ret = pgetaddrinfo("", "0", NULL, &result);
ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
ok(result != NULL, "getaddrinfo failed\n");
- pfreeaddrinfo(result);
- result = NULL;
- ret = pgetaddrinfo("", "", NULL, &result);
+ result2 = NULL;
+ ret = pgetaddrinfo("", "", NULL, &result2);
ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
- ok(result != NULL, "getaddrinfo failed\n");
+ ok(result2 != NULL, "getaddrinfo failed\n");
+ compare_addrinfo(result, result2);
pfreeaddrinfo(result);
+ pfreeaddrinfo(result2);
result = NULL;
ret = pgetaddrinfo("localhost", NULL, NULL, &result);
More information about the wine-patches
mailing list