From 20e2edba076a4b452d3246e771ed13a6bed6753e Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Sat, 5 Mar 2022 22:04:03 +0300 Subject: [PATCH] ws2_32: Pre-validate optlen in getsockopt(). Signed-off-by: Paul Gofman Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/ws2_32/socket.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index e5e29107853..30dc007167a 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1395,11 +1395,18 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl TRACE( "socket %#Ix, %s, optval %p, optlen %p (%d)\n", s, debugstr_sockopt(level, optname), optval, optlen, optlen ? *optlen : 0 ); - if ((level != SOL_SOCKET || optname != SO_OPENTYPE) && - !socket_list_find( s )) + if ((level != SOL_SOCKET || optname != SO_OPENTYPE)) { - SetLastError( WSAENOTSOCK ); - return SOCKET_ERROR; + if (!socket_list_find( s )) + { + SetLastError( WSAENOTSOCK ); + return SOCKET_ERROR; + } + if (!optlen || *optlen <= 0) + { + SetLastError( WSAEFAULT ); + return -1; + } } switch(level) @@ -1464,7 +1471,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl } case SO_CONNECT_TIME: - if (!optlen || !optval) + if (!optval) { SetLastError( WSAEFAULT ); return -1; @@ -1483,7 +1490,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl int len = sizeof(linger); int ret; - if (!optlen || *optlen < sizeof(BOOL)|| !optval) + if (*optlen < sizeof(BOOL)|| !optval) { SetLastError(WSAEFAULT); return SOCKET_ERROR; @@ -1500,7 +1507,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl /* As mentioned in setsockopt, Windows ignores this, so we * always return true here */ case SO_DONTROUTE: - if (!optlen || *optlen < sizeof(BOOL) || !optval) + if (*optlen < sizeof(BOOL) || !optval) { SetLastError(WSAEFAULT); return SOCKET_ERROR; @@ -1521,7 +1528,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl int size; /* struct linger and LINGER have different sizes */ - if (!optlen || *optlen < sizeof(LINGER) || !optval) + if (*optlen < sizeof(LINGER) || !optval) { SetLastError(WSAEFAULT); return SOCKET_ERROR; @@ -1540,7 +1547,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl } case SO_MAX_MSG_SIZE: - if (!optlen || *optlen < sizeof(int) || !optval) + if (*optlen < sizeof(int) || !optval) { SetLastError(WSAEFAULT); return SOCKET_ERROR; @@ -1574,9 +1581,9 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl ret = ws_protocol_info(s, optname == SO_PROTOCOL_INFOW, &infow, &size); if (ret) { - if (!optlen || !optval || *optlen < size) + if (!optval || *optlen < size) { - if(optlen) *optlen = size; + *optlen = size; ret = 0; SetLastError(WSAEFAULT); } @@ -1606,7 +1613,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl WSAPROTOCOL_INFOW info; int size; - if (!optlen || *optlen < sizeof(int) || !optval) + if (*optlen < sizeof(int) || !optval) { SetLastError(WSAEFAULT); return SOCKET_ERROR; @@ -1765,7 +1772,7 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl return server_getsockopt( s, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP, optval, optlen ); case IPV6_PROTECTION_LEVEL: - if (!optlen || *optlen < sizeof(UINT) || !optval) + if (*optlen < sizeof(UINT) || !optval) { SetLastError( WSAEFAULT ); return -1;