winhttp: Consider short read from netconn_recv() in receive_bytes().

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-01-20 18:35:34 +03:00 committed by Alexandre Julliard
parent 3a914ff488
commit b5b066f62a
1 changed files with 22 additions and 10 deletions

View File

@ -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;