[PATCH 2/2] ws2_32: Reimplement WSAStringToAddress on top of ntdll functions
Alex Henrie
alexhenrie24 at gmail.com
Fri May 15 09:54:47 CDT 2020
And add tests to show that the address is always zeroed out even if
there is an error.
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/ws2_32/socket.c | 82 +++++++---------------------------------
dlls/ws2_32/tests/sock.c | 9 +++--
2 files changed, 19 insertions(+), 72 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d688994e62..a5df51d421 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -154,6 +154,7 @@
#include "winnt.h"
#define USE_WC_PREFIX /* For CMSG_DATA */
#include "iphlpapi.h"
+#include "ip2string.h"
#include "wine/server.h"
#include "wine/debug.h"
#include "wine/exception.h"
@@ -8484,7 +8485,7 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
LPINT lpAddressLength)
{
INT res=0;
- LPSTR workBuffer=NULL,ptrPort;
+ NTSTATUS status;
TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_a(AddressString), AddressFamily,
lpProtocolInfo, lpAddress, lpAddressLength );
@@ -8500,21 +8501,11 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
if (lpProtocolInfo)
FIXME("ProtocolInfo not implemented.\n");
- workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- strlen(AddressString) + 1);
- if (!workBuffer)
- {
- SetLastError(WSA_NOT_ENOUGH_MEMORY);
- return SOCKET_ERROR;
- }
-
- strcpy(workBuffer, AddressString);
-
switch(AddressFamily)
{
case WS_AF_INET:
{
- struct in_addr inetaddr;
+ SOCKADDR_IN *addr4 = (SOCKADDR_IN *)lpAddress;
/* If lpAddressLength is too small, tell caller the size we need */
if (*lpAddressLength < sizeof(SOCKADDR_IN))
@@ -8526,35 +8517,18 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
*lpAddressLength = sizeof(SOCKADDR_IN);
memset(lpAddress, 0, sizeof(SOCKADDR_IN));
- ((LPSOCKADDR_IN)lpAddress)->sin_family = WS_AF_INET;
-
- ptrPort = strchr(workBuffer, ':');
- if(ptrPort)
- {
- /* User may have entered an IPv6 and asked to parse as IPv4 */
- if(strchr(ptrPort + 1, ':'))
- {
- res = WSAEINVAL;
- break;
- }
- ((LPSOCKADDR_IN)lpAddress)->sin_port = htons(atoi(ptrPort+1));
- *ptrPort = '\0';
- }
-
- if(inet_aton(workBuffer, &inetaddr) > 0)
+ status = RtlIpv4StringToAddressExA(AddressString, FALSE, &addr4->sin_addr, &addr4->sin_port);
+ if (status != STATUS_SUCCESS)
{
- ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
- res = 0;
- }
- else
res = WSAEINVAL;
-
+ break;
+ }
+ addr4->sin_family = WS_AF_INET;
break;
}
case WS_AF_INET6:
{
- struct in6_addr inetaddr;
- char *ptrAddr = workBuffer;
+ SOCKADDR_IN6 *addr6 = (SOCKADDR_IN6 *)lpAddress;
/* If lpAddressLength is too small, tell caller the size we need */
if (*lpAddressLength < sizeof(SOCKADDR_IN6))
@@ -8563,42 +8537,16 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
res = WSAEFAULT;
break;
}
-#ifdef HAVE_INET_PTON
*lpAddressLength = sizeof(SOCKADDR_IN6);
memset(lpAddress, 0, sizeof(SOCKADDR_IN6));
- ((LPSOCKADDR_IN6)lpAddress)->sin6_family = WS_AF_INET6;
-
- /* Valid IPv6 addresses can also be surrounded by [ ], and in this case
- * a port number may follow after like in [fd12:3456:7890::1]:12345
- * We need to cut the brackets and find the port if any. */
-
- if(*workBuffer == '[')
- {
- ptrPort = strchr(workBuffer, ']');
- if (!ptrPort)
- {
- SetLastError(WSAEINVAL);
- return SOCKET_ERROR;
- }
-
- if (ptrPort[1] == ':')
- ((LPSOCKADDR_IN6)lpAddress)->sin6_port = htons(atoi(ptrPort + 2));
-
- *ptrPort = '\0';
- ptrAddr = workBuffer + 1;
- }
-
- if(inet_pton(AF_INET6, ptrAddr, &inetaddr) > 0)
+ status = RtlIpv6StringToAddressExA(AddressString, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port);
+ if (status != STATUS_SUCCESS)
{
- memcpy(&((LPSOCKADDR_IN6)lpAddress)->sin6_addr, &inetaddr,
- sizeof(struct in6_addr));
- res = 0;
- }
- else
-#endif /* HAVE_INET_PTON */
res = WSAEINVAL;
-
+ break;
+ }
+ addr6->sin6_family = WS_AF_INET6;
break;
}
default:
@@ -8607,8 +8555,6 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString,
res = WSAEINVAL;
}
- HeapFree(GetProcessHeap(), 0, workBuffer);
-
if (!res) return 0;
SetLastError(res);
return SOCKET_ERROR;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index d77ee833cd..85933f7386 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -3429,6 +3429,8 @@ static void test_WSAStringToAddress(void)
{ "127.127.127.127:65535", 0x7f7f7f7f, 65535 },
{ "255.255.255.255:65535", 0xffffffff, 65535 },
{ "2001::1", 0xd1070000, 0, WSAEINVAL },
+ { "1.2.3.", 0, 0, WSAEINVAL },
+ { "", 0, 0, WSAEINVAL },
};
static struct
{
@@ -3445,6 +3447,9 @@ static void test_WSAStringToAddress(void)
{ "2001::1", { 0x120, 0, 0, 0, 0, 0, 0, 0x100 } },
{ "::1]:65535", { 0, 0, 0, 0, 0, 0, 0, 0x100 }, 0, WSAEINVAL },
{ "001::1", { 0x100, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "1.2.3.4", { 0x201, 0x3, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL },
+ { "1:2:3:", { 0x100, 0x200, 0x300, 0, 0, 0, 0 }, 0, WSAEINVAL },
+ { "", { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, WSAEINVAL },
};
WCHAR inputW[64];
@@ -3488,11 +3493,9 @@ static void test_WSAStringToAddress(void)
ok( WSAGetLastError() == ipv4_tests[j].error,
"WSAStringToAddress(%s) gave error %d, expected %d\n",
wine_dbgstr_a( ipv4_tests[j].input ), WSAGetLastError(), ipv4_tests[j].error );
-todo_wine_if(ipv4_tests[j].error)
ok( sockaddr.sin_family == expected_family,
"WSAStringToAddress(%s) gave family %d, expected %d\n",
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_family, expected_family );
-todo_wine_if(ipv4_tests[j].error)
ok( sockaddr.sin_addr.s_addr == ipv4_tests[j].address,
"WSAStringToAddress(%s) gave address %08x, expected %08x\n",
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr.sin_addr.s_addr, ipv4_tests[j].address );
@@ -3532,11 +3535,9 @@ todo_wine_if(ipv4_tests[j].error)
ok( WSAGetLastError() == ipv6_tests[j].error,
"WSAStringToAddress(%s) gave error %d, expected %d\n",
wine_dbgstr_a( ipv6_tests[j].input ), WSAGetLastError(), ipv6_tests[j].error );
-todo_wine_if(ipv6_tests[j].error)
ok( sockaddr6.sin6_family == expected_family,
"WSAStringToAddress(%s) gave family %d, expected %d\n",
wine_dbgstr_a( ipv4_tests[j].input ), sockaddr6.sin6_family );
-todo_wine_if(ipv6_tests[j].error)
ok( sockaddr6.sin6_addr.s6_words[0] == ipv6_tests[j].address[0] &&
sockaddr6.sin6_addr.s6_words[1] == ipv6_tests[j].address[1] &&
sockaddr6.sin6_addr.s6_words[2] == ipv6_tests[j].address[2] &&
--
2.26.2
More information about the wine-devel
mailing list