Module: wine Branch: master Commit: 1bcc3aa35ca21b64d98f9777967bb6ccf98af567 URL: http://source.winehq.org/git/wine.git/?a=commit;h=1bcc3aa35ca21b64d98f977796...
Author: Andrew Nguyen arethusa26@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();