Merge pull request #4481 from akallabeth/fastpath_fix

Fastpath uncompressed length issue
This commit is contained in:
MartinHaimberger 2018-04-05 10:17:51 +02:00 committed by GitHub
commit 0af63d4c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 90 deletions

View File

@ -328,7 +328,7 @@ static BOOL fastpath_recv_update_synchronize(rdpFastPath* fastpath, wStream* s)
return TRUE;
}
static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 size, wStream* s)
static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, wStream* s)
{
int status = 0;
rdpUpdate* update;
@ -346,9 +346,9 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
context = update->context;
pointer = update->pointer;
#ifdef WITH_DEBUG_RDP
DEBUG_RDP("recv Fast-Path %s Update (0x%02"PRIX8"), length:%"PRIu32"",
DEBUG_RDP("recv Fast-Path %s Update (0x%02"PRIX8"), length:%"PRIuz"",
updateCode < ARRAYSIZE(FASTPATH_UPDATETYPE_STRINGS) ? FASTPATH_UPDATETYPE_STRINGS[updateCode] :
"???", updateCode, size);
"???", updateCode, Stream_GetLength(s));
#endif
switch (updateCode)
@ -451,10 +451,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
int status;
UINT16 size;
rdpRdp* rdp;
size_t next_pos;
wStream* cs;
int bulkStatus;
UINT32 totalSize;
BYTE updateCode;
BYTE fragmentation;
BYTE compression;
@ -501,10 +498,9 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
return -1;
}
cs = s;
next_pos = Stream_GetPosition(s) + size;
bulkStatus = bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize,
compressionFlags);
Stream_Seek(s, size);
if (bulkStatus < 0)
{
@ -512,19 +508,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
return -1;
}
if (bulkStatus > 0)
{
/* data was compressed, copy from decompression buffer */
size = DstSize;
if (!Stream_EnsureRemainingCapacity(fastpath->updateData, DstSize))
return -1;
if (!(cs = StreamPool_Take(transport->ReceivePool, DstSize)))
return -1;
Stream_SetPosition(cs, 0);
Stream_Write(cs, pDstData, DstSize);
Stream_SealLength(cs);
Stream_SetPosition(cs, 0);
}
Stream_Write(fastpath->updateData, pDstData, DstSize);
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
{
@ -534,8 +521,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
goto out_fail;
}
totalSize = size;
status = fastpath_recv_update(fastpath, updateCode, totalSize, cs);
Stream_SealLength(fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
status = fastpath_recv_update(fastpath, updateCode, fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
if (status < 0)
{
@ -545,6 +534,14 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
else
{
const size_t totalSize = Stream_GetPosition(fastpath->updateData);
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
WLog_ERR(TAG, "Total size (%"PRIuz") exceeds MultifragMaxRequestSize (%"PRIu32")",
totalSize, transport->settings->MultifragMaxRequestSize);
goto out_fail;
}
if (fragmentation == FASTPATH_FRAGMENT_FIRST)
{
if (fastpath->fragmentation != -1)
@ -554,20 +551,8 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
fastpath->fragmentation = FASTPATH_FRAGMENT_FIRST;
totalSize = size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")",
totalSize, transport->settings->MultifragMaxRequestSize);
goto out_fail;
}
if (!(fastpath->updateData = StreamPool_Take(transport->ReceivePool, size)))
goto out_fail;
Stream_SetPosition(fastpath->updateData, 0);
Stream_Copy(cs, fastpath->updateData, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
{
@ -579,22 +564,6 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
fastpath->fragmentation = FASTPATH_FRAGMENT_NEXT;
totalSize = Stream_GetPosition(fastpath->updateData) + size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")",
totalSize, transport->settings->MultifragMaxRequestSize);
goto out_fail;
}
if (!Stream_EnsureCapacity(fastpath->updateData, totalSize))
{
WLog_ERR(TAG, "Couldn't re-allocate memory for stream");
goto out_fail;
}
Stream_Copy(cs, fastpath->updateData, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
@ -606,26 +575,11 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
fastpath->fragmentation = -1;
totalSize = Stream_GetPosition(fastpath->updateData) + size;
if (totalSize > transport->settings->MultifragMaxRequestSize)
{
WLog_ERR(TAG, "Total size (%"PRIu32") exceeds MultifragMaxRequestSize (%"PRIu32")",
totalSize, transport->settings->MultifragMaxRequestSize);
goto out_fail;
}
if (!Stream_EnsureCapacity(fastpath->updateData, totalSize))
{
WLog_ERR(TAG, "Couldn't re-allocate memory for stream");
goto out_fail;
}
Stream_Copy(cs, fastpath->updateData, size);
Stream_SealLength(fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
status = fastpath_recv_update(fastpath, updateCode, totalSize, fastpath->updateData);
Stream_Release(fastpath->updateData);
status = fastpath_recv_update(fastpath, updateCode, fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
if (status < 0)
{
@ -635,19 +589,9 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
}
}
Stream_SetPosition(s, next_pos);
if (cs != s)
Stream_Release(cs);
return status;
out_fail:
if (cs != s)
{
Stream_Release(cs);
}
return -1;
}
@ -1244,13 +1188,14 @@ rdpFastPath* fastpath_new(rdpRdp* rdp)
fastpath->rdp = rdp;
fastpath->fragmentation = -1;
fastpath->fs = Stream_New(NULL, FASTPATH_MAX_PACKET_SIZE);
fastpath->updateData = Stream_New(NULL, FASTPATH_MAX_PACKET_SIZE);
if (!fastpath->fs)
if (!fastpath->fs || !fastpath->updateData)
goto out_free;
return fastpath;
out_free:
free(fastpath);
fastpath_free(fastpath);
return NULL;
}
@ -1258,6 +1203,7 @@ void fastpath_free(rdpFastPath* fastpath)
{
if (fastpath)
{
Stream_Free(fastpath->updateData, TRUE);
Stream_Free(fastpath->fs, TRUE);
free(fastpath);
}

View File

@ -236,17 +236,14 @@ BOOL freerdp_connect(freerdp* instance)
update = instance->update;
update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
status = FALSE;
if (!update->pcap_rfx)
{
status = FALSE;
goto freerdp_connect_finally;
}
else
{
update->play_rfx = TRUE;
}
while (pcap_has_next_record(update->pcap_rfx))
status = TRUE;
while (pcap_has_next_record(update->pcap_rfx) && status)
{
pcap_get_next_record_header(update->pcap_rfx, &record);
@ -257,15 +254,19 @@ BOOL freerdp_connect(freerdp* instance)
pcap_get_next_record_content(update->pcap_rfx, &record);
Stream_SetLength(s, record.length);
Stream_SetPosition(s, 0);
update->BeginPaint(update->context);
update_recv_surfcmds(update, s);
update->EndPaint(update->context);
if (!update->BeginPaint(update->context))
status = FALSE;
else if (update_recv_surfcmds(update, s) < 0)
status = FALSE;
else if (!update->EndPaint(update->context))
status = FALSE;
Stream_Release(s);
}
pcap_close(update->pcap_rfx);
update->pcap_rfx = NULL;
status = TRUE;
goto freerdp_connect_finally;
}
}