[PATCH 1/3] ws2_32: WSARecvMsg allows a NULL control buffer when no control messages arrive

Damjan Jovanovic damjan.jov at gmail.com
Wed Jul 31 23:11:21 CDT 2019


Wine's WSARecvFrom() cannot distinguish between:
1. truncation during conversion of cmsghdrs from *nix to Windows,
which is an error.
2. a NULL WSAMSG.Control.buf passed in by the application, which is valid
   when there is no control data to convert.

Wine always treats it as case (1) and reports an error.

Closes bug 43286.

Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
 dlls/ws2_32/socket.c     |  8 +++++---
 dlls/ws2_32/tests/sock.c | 17 +++++++++++++++--
 2 files changed, 20 insertions(+), 5 deletions(-)
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 3b78f0de5d..a3c37806bb 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -878,10 +878,12 @@ static inline int convert_control_headers(struct msghdr *hdr, WSABUF *control)
         }
     }
 
-error:
     /* Set the length of the returned control headers */
-    control->len = (ptr == NULL ? 0 : (char*)ptr - (char*)cmsg_win);
-    return (ptr != NULL);
+    control->len = (char*)ptr - (char*)cmsg_win;
+    return 1;
+error:
+    control->len = 0;
+    return 0;
 #else /* IP_PKTINFO */
     control->len = 0;
     return 1;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 0c7f7363be..03f4e6859e 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -2108,8 +2108,6 @@ static void test_ip_pktinfo(void)
         /* Setup the server side socket */
         rc=bind(s1, (struct sockaddr*)&s1addr, sizeof(s1addr));
         ok(rc != SOCKET_ERROR, "bind() failed error: %d\n", WSAGetLastError());
-        rc=setsockopt(s1, IPPROTO_IP, IP_PKTINFO, (const char*)&yes, sizeof(yes));
-        ok(rc == 0, "failed to set IPPROTO_IP flag IP_PKTINFO!\n");
 
         /* Build "client" side socket */
         addrlen = sizeof(s2addr);
@@ -2133,6 +2131,21 @@ static void test_ip_pktinfo(void)
         err=WSAGetLastError();
         ok(rc == SOCKET_ERROR && err == WSAEFAULT, "WSARecvMsg() failed error: %d (ret = %d)\n", err, rc);
 
+        /* Test that when no control data arrives, a 0-length NULL-valued control buffer should succeed */
+        SetLastError(0xdeadbeef);
+        rc=sendto(s2, msg, sizeof(msg), 0, (struct sockaddr*)&s2addr, sizeof(s2addr));
+        ok(rc == sizeof(msg), "sendto() failed error: %d\n", WSAGetLastError());
+        ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+        hdr.Control.buf = NULL;
+        hdr.Control.len = 0;
+        rc=pWSARecvMsg(s1, &hdr, &dwSize, NULL, NULL);
+        ok(rc == 0, "WSARecvMsg() failed error: %d\n", WSAGetLastError());
+        hdr.Control.buf = pktbuf;
+
+        /* Now start IP_PKTINFO for future tests */
+        rc=setsockopt(s1, IPPROTO_IP, IP_PKTINFO, (const char*)&yes, sizeof(yes));
+        ok(rc == 0, "failed to set IPPROTO_IP flag IP_PKTINFO!\n");
+
         /*
          * Send a packet from the client to the server and test for specifying
          * a short control header.


More information about the wine-devel mailing list