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