Andrew Nguyen : ws2_32: Fix parameter validation order in getpeername.

Alexandre Julliard julliard at winehq.org
Wed Feb 3 09:33:03 CST 2010


Module: wine
Branch: master
Commit: 1bcc3aa35ca21b64d98f9777967bb6ccf98af567
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1bcc3aa35ca21b64d98f9777967bb6ccf98af567

Author: Andrew Nguyen <arethusa26 at gmail.com>
Date:   Wed Feb  3 01:18:40 2010 -0600

ws2_32: Fix parameter validation order in getpeername.

---

 dlls/ws2_32/socket.c     |   27 ++++++----------
 dlls/ws2_32/tests/sock.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 17 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 9a65cb0..a9e9538 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -149,6 +149,7 @@
 #include "iphlpapi.h"
 #include "wine/server.h"
 #include "wine/debug.h"
+#include "wine/exception.h"
 #include "wine/unicode.h"
 
 #ifdef HAVE_IPX
@@ -1796,13 +1797,6 @@ int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
 
     TRACE("socket: %04lx, ptr %p, len %08x\n", s, name, *namelen);
 
-    /* Check if what we've received is valid. Should we use IsBadReadPtr? */
-    if( (name == NULL) || (namelen == NULL) )
-    {
-        SetLastError( WSAEFAULT );
-        return SOCKET_ERROR;
-    }
-
     fd = get_sock_fd( s, 0, NULL );
     res = SOCKET_ERROR;
 
@@ -1811,19 +1805,18 @@ int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
         union generic_unix_sockaddr uaddr;
         unsigned int uaddrlen = sizeof(uaddr);
 
-        if (getpeername(fd, &uaddr.addr, &uaddrlen) != 0)
-        {
-            SetLastError(wsaErrno());
-        }
-        else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
+        if (getpeername(fd, &uaddr.addr, &uaddrlen) == 0)
         {
-            /* The buffer was too small */
-            SetLastError(WSAEFAULT);
+            if (!name || !namelen)
+                SetLastError(WSAEFAULT);
+            else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
+                /* The buffer was too small */
+                SetLastError(WSAEFAULT);
+            else
+                res = 0;
         }
         else
-        {
-            res=0;
-        }
+            SetLastError(wsaErrno());
         release_sock_fd( s, fd );
     }
     return res;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index fbe55f6..72242c4 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -3257,6 +3257,81 @@ end:
         closesocket(connector2);
 }
 
+static void test_getpeername(void)
+{
+    SOCKET sock;
+    struct sockaddr_in sa, sa_out;
+    int sa_len;
+    const char buf[] = "hello world";
+    int ret;
+
+    /* Test the parameter validation order. */
+    ret = getpeername(INVALID_SOCKET, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return SOCKET_ERROR, got %d\n", ret);
+    ok(WSAGetLastError() == WSAENOTSOCK,
+       "Expected WSAGetLastError() to return WSAENOTSOCK, got %d\n", WSAGetLastError());
+
+    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+    ok(sock != INVALID_SOCKET, "Expected socket to return a valid socket\n");
+    if (sock == INVALID_SOCKET)
+    {
+        skip("Socket creation failed with %d\n", WSAGetLastError());
+        return;
+    }
+
+    ret = getpeername(sock, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return SOCKET_ERROR, got %d\n", ret);
+    ok(WSAGetLastError() == WSAENOTCONN,
+       "Expected WSAGetLastError() to return WSAENOTCONN, got %d\n", WSAGetLastError());
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons(139);
+    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    /* sendto does not change a socket's connection state. */
+    ret = sendto(sock, buf, sizeof(buf), 0, (struct sockaddr*)&sa, sizeof(sa));
+    ok(ret != SOCKET_ERROR,
+       "Expected sendto to succeed, WSAGetLastError() = %d\n", WSAGetLastError());
+
+    ret = getpeername(sock, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return SOCKET_ERROR, got %d\n", ret);
+    ok(WSAGetLastError() == WSAENOTCONN,
+       "Expected WSAGetLastError() to return WSAENOTCONN, got %d\n", WSAGetLastError());
+
+    ret = connect(sock, (struct sockaddr*)&sa, sizeof(sa));
+    ok(ret == 0,
+       "Expected connect to succeed, WSAGetLastError() = %d\n", WSAGetLastError());
+
+    ret = getpeername(sock, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return SOCKET_ERROR, got %d\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT,
+       "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+
+    /* Test crashes on Wine. */
+    if (0)
+    {
+        ret = getpeername(sock, (void*)0xdeadbeef, (void*)0xcafebabe);
+        ok(ret == SOCKET_ERROR, "Expected getpeername to return SOCKET_ERROR, got %d\n", ret);
+        ok(WSAGetLastError() == WSAEFAULT,
+           "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+    }
+
+    sa_len = 0;
+    ret = getpeername(sock, (struct sockaddr*)&sa_out, &sa_len);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return 0, got %d\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT,
+       "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+
+    sa_len = sizeof(sa_out);
+    ret = getpeername(sock, (struct sockaddr*)&sa_out, &sa_len);
+    ok(ret == 0, "Expected getpeername to return 0, got %d\n", ret);
+    ok(!memcmp(&sa, &sa_out, sizeof(sa)),
+       "Expected the returned structure to be identical to the connect structure\n");
+
+    closesocket(sock);
+}
+
 /**************** Main program  ***************/
 
 START_TEST( sock )
@@ -3294,6 +3369,7 @@ START_TEST( sock )
 
     test_select();
     test_accept();
+    test_getpeername();
     test_getsockname();
     test_inet_addr();
     test_addr_to_print();




More information about the wine-cvs mailing list