[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