[PATCH 5/5] winhttp: Consider short read from netconn_recv() in receive_bytes().
Paul Gofman
pgofman at codeweavers.com
Thu Jan 20 09:35:34 CST 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/winhttp/request.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index f215b984f6e..af04292ea06 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3328,7 +3328,7 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
return ret;
}
-static DWORD receive_bytes( struct socket *socket, char *buf, DWORD len, DWORD *ret_len )
+static DWORD receive_bytes( struct socket *socket, char *buf, DWORD len, DWORD *ret_len, BOOL read_full_buffer )
{
DWORD err, size = 0, needed = len;
char *ptr = buf;
@@ -3342,8 +3342,17 @@ static DWORD receive_bytes( struct socket *socket, char *buf, DWORD len, DWORD *
needed -= size;
ptr += size;
}
- if ((err = netconn_recv( socket->request->netconn, ptr, needed, 0, &received ))) return err;
- if ((*ret_len = size + received) != len) return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
+ while (size != len)
+ {
+ if ((err = netconn_recv( socket->request->netconn, ptr, needed, 0, &received ))) return err;
+ if (!received) break;
+ size += received;
+ if (!read_full_buffer) break;
+ needed -= received;
+ ptr += received;
+ }
+ *ret_len = size;
+ if (size != len && (read_full_buffer || !size)) return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
return ERROR_SUCCESS;
}
@@ -3368,7 +3377,7 @@ static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_o
DWORD ret, len, count;
char hdr[2];
- if ((ret = receive_bytes( socket, hdr, sizeof(hdr), &count ))) return ret;
+ if ((ret = receive_bytes( socket, hdr, sizeof(hdr), &count, TRUE ))) return ret;
if ((hdr[0] & RESERVED_BIT) || (hdr[1] & MASK_BIT) || !is_supported_opcode( hdr[0] & 0xf ))
{
return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
@@ -3380,13 +3389,13 @@ static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_o
if (len == 126)
{
USHORT len16;
- if ((ret = receive_bytes( socket, (char *)&len16, sizeof(len16), &count ))) return ret;
+ if ((ret = receive_bytes( socket, (char *)&len16, sizeof(len16), &count, TRUE ))) return ret;
len = RtlUshortByteSwap( len16 );
}
else if (len == 127)
{
ULONGLONG len64;
- if ((ret = receive_bytes( socket, (char *)&len64, sizeof(len64), &count ))) return ret;
+ if ((ret = receive_bytes( socket, (char *)&len64, sizeof(len64), &count, TRUE ))) return ret;
if ((len64 = RtlUlonglongByteSwap( len64 )) > ~0u) return ERROR_NOT_SUPPORTED;
len = len64;
}
@@ -3434,7 +3443,7 @@ static DWORD socket_drain( struct socket *socket )
while (socket->read_size)
{
char buf[1024];
- if ((ret = receive_bytes( socket, buf, min(socket->read_size, sizeof(buf)), &count ))) return ret;
+ if ((ret = receive_bytes( socket, buf, min(socket->read_size, sizeof(buf)), &count, TRUE ))) return ret;
socket->read_size -= count;
}
return ERROR_SUCCESS;
@@ -3496,9 +3505,12 @@ static DWORD socket_receive( struct socket *socket, void *buf, DWORD len, DWORD
if (ret) break;
}
}
- if (!ret) ret = receive_bytes( socket, buf, min(len, socket->read_size), &count );
+ if (!ret) ret = receive_bytes( socket, buf, min(len, socket->read_size), &count, FALSE );
if (!ret)
{
+ if (count < socket->read_size)
+ WARN("Short read.\n");
+
socket->read_size -= count;
if (!async)
{
@@ -3685,9 +3697,9 @@ static DWORD socket_close( struct socket *socket, USHORT status, const void *rea
if (count)
{
DWORD reason_len = count - sizeof(socket->status);
- if ((ret = receive_bytes( socket, (char *)&socket->status, sizeof(socket->status), &count ))) goto done;
+ if ((ret = receive_bytes( socket, (char *)&socket->status, sizeof(socket->status), &count, TRUE ))) goto done;
socket->status = RtlUshortByteSwap( socket->status );
- if ((ret = receive_bytes( socket, socket->reason, reason_len, &socket->reason_len ))) goto done;
+ if ((ret = receive_bytes( socket, socket->reason, reason_len, &socket->reason_len, TRUE ))) goto done;
}
socket->state = SOCKET_STATE_CLOSED;
--
2.34.1
More information about the wine-devel
mailing list