From 1bcc3aa35ca21b64d98f9777967bb6ccf98af567 Mon Sep 17 00:00:00 2001 From: Andrew Nguyen Date: Wed, 3 Feb 2010 01:18:40 -0600 Subject: [PATCH] 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 9a65cb01f9e..a9e953893d8 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 fbe55f6c31e..72242c4c82e 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(); -- 2.11.4.GIT