ws2_32: Cope with invalid hints in getaddrinfo/GetAddrInfoW.
This commit is contained in:
parent
3eb39dc08e
commit
719715c774
|
@ -5464,19 +5464,33 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
|
|||
punixhints = &unixhints;
|
||||
|
||||
memset(&unixhints, 0, sizeof(unixhints));
|
||||
punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
|
||||
if (hints->ai_family == 0) /* wildcard, specific to getaddrinfo() */
|
||||
punixhints->ai_family = 0;
|
||||
else
|
||||
punixhints->ai_flags = convert_aiflag_w2u(hints->ai_flags);
|
||||
|
||||
/* zero is a wildcard, no need to convert */
|
||||
if (hints->ai_family)
|
||||
punixhints->ai_family = convert_af_w2u(hints->ai_family);
|
||||
if (hints->ai_socktype == 0) /* wildcard, specific to getaddrinfo() */
|
||||
punixhints->ai_socktype = 0;
|
||||
else
|
||||
if (hints->ai_socktype)
|
||||
punixhints->ai_socktype = convert_socktype_w2u(hints->ai_socktype);
|
||||
if (hints->ai_protocol == 0) /* wildcard, specific to getaddrinfo() */
|
||||
punixhints->ai_protocol = 0;
|
||||
else
|
||||
punixhints->ai_protocol = convert_proto_w2u(hints->ai_protocol);
|
||||
if (hints->ai_protocol)
|
||||
punixhints->ai_protocol = max(convert_proto_w2u(hints->ai_protocol), 0);
|
||||
|
||||
if (punixhints->ai_socktype < 0)
|
||||
{
|
||||
WSASetLastError(WSAESOCKTNOSUPPORT);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
/* windows allows invalid combinations of socket type and protocol, unix does not.
|
||||
* fix the parameters here to make getaddrinfo call always work */
|
||||
if (punixhints->ai_protocol == IPPROTO_TCP &&
|
||||
punixhints->ai_socktype != SOCK_STREAM && punixhints->ai_socktype != SOCK_SEQPACKET)
|
||||
punixhints->ai_socktype = 0;
|
||||
|
||||
else if (punixhints->ai_protocol == IPPROTO_UDP && punixhints->ai_socktype != SOCK_DGRAM)
|
||||
punixhints->ai_socktype = 0;
|
||||
|
||||
else if (IS_IPX_PROTO(punixhints->ai_protocol) && punixhints->ai_socktype != SOCK_DGRAM)
|
||||
punixhints->ai_socktype = 0;
|
||||
}
|
||||
|
||||
/* getaddrinfo(3) is thread safe, no need to wrap in CS */
|
||||
|
@ -5500,8 +5514,14 @@ int WINAPI WS_getaddrinfo(LPCSTR nodename, LPCSTR servname, const struct WS_addr
|
|||
*xai = ai;xai = &ai->ai_next;
|
||||
ai->ai_flags = convert_aiflag_u2w(xuai->ai_flags);
|
||||
ai->ai_family = convert_af_u2w(xuai->ai_family);
|
||||
ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
|
||||
ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
|
||||
/* copy whatever was sent in the hints */
|
||||
if(hints) {
|
||||
ai->ai_socktype = hints->ai_socktype;
|
||||
ai->ai_protocol = hints->ai_protocol;
|
||||
} else {
|
||||
ai->ai_socktype = convert_socktype_u2w(xuai->ai_socktype);
|
||||
ai->ai_protocol = convert_proto_u2w(xuai->ai_protocol);
|
||||
}
|
||||
if (xuai->ai_canonname) {
|
||||
TRACE("canon name - %s\n",debugstr_a(xuai->ai_canonname));
|
||||
ai->ai_canonname = HeapAlloc(GetProcessHeap(),0,strlen(xuai->ai_canonname)+1);
|
||||
|
|
|
@ -149,6 +149,38 @@ typedef struct select_thread_params
|
|||
BOOL ReadKilled;
|
||||
} select_thread_params;
|
||||
|
||||
/* Tests used in both getaddrinfo and GetAddrInfoW */
|
||||
static const struct addr_hint_tests
|
||||
{
|
||||
int family, socktype, protocol;
|
||||
DWORD error;
|
||||
} hinttests[] = {
|
||||
{AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0 },
|
||||
{AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP, 0 },
|
||||
{AF_UNSPEC, SOCK_DGRAM, IPPROTO_TCP, 0 },
|
||||
{AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, 0 },
|
||||
{AF_INET, SOCK_STREAM, IPPROTO_TCP, 0 },
|
||||
{AF_INET, SOCK_STREAM, IPPROTO_UDP, 0 },
|
||||
{AF_INET, SOCK_DGRAM, IPPROTO_TCP, 0 },
|
||||
{AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0 },
|
||||
{AF_UNSPEC, 0, IPPROTO_TCP, 0 },
|
||||
{AF_UNSPEC, 0, IPPROTO_UDP, 0 },
|
||||
{AF_UNSPEC, SOCK_STREAM, 0, 0 },
|
||||
{AF_UNSPEC, SOCK_DGRAM, 0, 0 },
|
||||
{AF_INET, 0, IPPROTO_TCP, 0 },
|
||||
{AF_INET, 0, IPPROTO_UDP, 0 },
|
||||
{AF_INET, SOCK_STREAM, 0, 0 },
|
||||
{AF_INET, SOCK_DGRAM, 0, 0 },
|
||||
{AF_UNSPEC, 999, IPPROTO_TCP, WSAESOCKTNOSUPPORT },
|
||||
{AF_UNSPEC, 999, IPPROTO_UDP, WSAESOCKTNOSUPPORT },
|
||||
{AF_INET, 999, IPPROTO_TCP, WSAESOCKTNOSUPPORT },
|
||||
{AF_INET, 999, IPPROTO_UDP, WSAESOCKTNOSUPPORT },
|
||||
{AF_UNSPEC, SOCK_STREAM, 999, 0 },
|
||||
{AF_UNSPEC, SOCK_STREAM, 999, 0 },
|
||||
{AF_INET, SOCK_DGRAM, 999, 0 },
|
||||
{AF_INET, SOCK_DGRAM, 999, 0 },
|
||||
};
|
||||
|
||||
/**************** Static variables ***************/
|
||||
|
||||
static DWORD tls; /* Thread local storage index */
|
||||
|
@ -5280,8 +5312,8 @@ static void test_GetAddrInfoW(void)
|
|||
static const WCHAR nxdomain[] =
|
||||
{'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 ret;
|
||||
ADDRINFOW *result, hint;
|
||||
int i, ret;
|
||||
ADDRINFOW *result, *p, hint;
|
||||
|
||||
if (!pGetAddrInfoW || !pFreeAddrInfoW)
|
||||
{
|
||||
|
@ -5352,12 +5384,63 @@ static void test_GetAddrInfoW(void)
|
|||
ret = pGetAddrInfoW(nxdomain, NULL, NULL, &result);
|
||||
ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
|
||||
ok(result == NULL, "got %p\n", result);
|
||||
|
||||
for (i = 0;i < (sizeof(hinttests) / sizeof(hinttests[0]));i++)
|
||||
{
|
||||
hint.ai_family = hinttests[i].family;
|
||||
hint.ai_socktype = hinttests[i].socktype;
|
||||
hint.ai_protocol = hinttests[i].protocol;
|
||||
|
||||
result = NULL;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pGetAddrInfoW(localhost, NULL, &hint, &result);
|
||||
if (!ret)
|
||||
{
|
||||
if (hinttests[i].error)
|
||||
ok(0, "test %d: GetAddrInfoW succeeded unexpectedly\n", i);
|
||||
else
|
||||
{
|
||||
p = result;
|
||||
do
|
||||
{
|
||||
/* when AF_UNSPEC is used the return will be either AF_INET or AF_INET6 */
|
||||
if (hinttests[i].family == AF_UNSPEC)
|
||||
ok(p->ai_family == AF_INET || p->ai_family == AF_INET6,
|
||||
"test %d: expected AF_INET or AF_INET6, got %d\n",
|
||||
i, p->ai_family);
|
||||
else
|
||||
ok(p->ai_family == hinttests[i].family,
|
||||
"test %d: expected family %d, got %d\n",
|
||||
i, hinttests[i].family, p->ai_family);
|
||||
|
||||
ok(p->ai_socktype == hinttests[i].socktype,
|
||||
"test %d: expected type %d, got %d\n",
|
||||
i, hinttests[i].socktype, p->ai_socktype);
|
||||
ok(p->ai_protocol == hinttests[i].protocol,
|
||||
"test %d: expected protocol %d, got %d\n",
|
||||
i, hinttests[i].protocol, p->ai_protocol);
|
||||
p = p->ai_next;
|
||||
}
|
||||
while (p);
|
||||
}
|
||||
pFreeAddrInfoW(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = WSAGetLastError();
|
||||
if (hinttests[i].error)
|
||||
ok(hinttests[i].error == err, "test %d: GetAddrInfoW failed with error %d, expected %d\n",
|
||||
i, err, hinttests[i].error);
|
||||
else
|
||||
ok(0, "test %d: GetAddrInfoW failed with %d (err %d)\n", i, ret, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_getaddrinfo(void)
|
||||
{
|
||||
int ret;
|
||||
ADDRINFOA *result, hint;
|
||||
int i, ret;
|
||||
ADDRINFOA *result, *p, hint;
|
||||
|
||||
if (!pgetaddrinfo || !pfreeaddrinfo)
|
||||
{
|
||||
|
@ -5423,6 +5506,57 @@ static void test_getaddrinfo(void)
|
|||
ret = pgetaddrinfo("nxdomain.codeweavers.com", NULL, NULL, &result);
|
||||
ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
|
||||
ok(result == NULL, "got %p\n", result);
|
||||
|
||||
for (i = 0;i < (sizeof(hinttests) / sizeof(hinttests[0]));i++)
|
||||
{
|
||||
hint.ai_family = hinttests[i].family;
|
||||
hint.ai_socktype = hinttests[i].socktype;
|
||||
hint.ai_protocol = hinttests[i].protocol;
|
||||
|
||||
result = NULL;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pgetaddrinfo("localhost", NULL, &hint, &result);
|
||||
if(!ret)
|
||||
{
|
||||
if (hinttests[i].error)
|
||||
ok(0, "test %d: getaddrinfo succeeded unexpectedly\n", i);
|
||||
else
|
||||
{
|
||||
p = result;
|
||||
do
|
||||
{
|
||||
/* when AF_UNSPEC is used the return will be either AF_INET or AF_INET6 */
|
||||
if (hinttests[i].family == AF_UNSPEC)
|
||||
ok(p->ai_family == AF_INET || p->ai_family == AF_INET6,
|
||||
"test %d: expected AF_INET or AF_INET6, got %d\n",
|
||||
i, p->ai_family);
|
||||
else
|
||||
ok(p->ai_family == hinttests[i].family,
|
||||
"test %d: expected family %d, got %d\n",
|
||||
i, hinttests[i].family, p->ai_family);
|
||||
|
||||
ok(p->ai_socktype == hinttests[i].socktype,
|
||||
"test %d: expected type %d, got %d\n",
|
||||
i, hinttests[i].socktype, p->ai_socktype);
|
||||
ok(p->ai_protocol == hinttests[i].protocol,
|
||||
"test %d: expected protocol %d, got %d\n",
|
||||
i, hinttests[i].protocol, p->ai_protocol);
|
||||
p = p->ai_next;
|
||||
}
|
||||
while (p);
|
||||
}
|
||||
pfreeaddrinfo(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = WSAGetLastError();
|
||||
if (hinttests[i].error)
|
||||
ok(hinttests[i].error == err, "test %d: getaddrinfo failed with error %d, expected %d\n",
|
||||
i, err, hinttests[i].error);
|
||||
else
|
||||
ok(0, "test %d: getaddrinfo failed with %d (err %d)\n", i, ret, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_ConnectEx(void)
|
||||
|
|
Loading…
Reference in New Issue