egfx: fix disconnection caused by invalid cache entries due to wrong announced cache size

Added some checks so that when setting a cache entry fails, we close connection (or
we fail later when trying to use that empty entry).
The small cache egfx capability has also been fixed.
This commit is contained in:
David Fort
2017-10-10 17:12:16 +02:00
parent 50d324655f
commit 5d5376faa7
3 changed files with 28 additions and 25 deletions

View File

@@ -74,7 +74,10 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
if (gfx->ThinClient)
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
if (gfx->SmallCache)
/* in CAPVERSION_8 the spec says that we should not have both
* thinclient and smallcache (and thinclient implies a small cache)
*/
if (gfx->SmallCache && !gfx->ThinClient)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
capsSet = &capsSets[pdu.capsSetCount++];
@@ -114,8 +117,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103;
}
header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount *
RDPGFX_CAPSET_SIZE);
header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE);
WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
s = Stream_New(NULL, header.pduLength);
@@ -1018,9 +1020,7 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
return ERROR_INVALID_DATA;
}
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount,
sizeof(RDPGFX_POINT16));
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
if (!pdu.destPts)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@@ -1637,7 +1637,11 @@ static UINT rdpgfx_set_cache_slot_data(RdpgfxClientContext* context,
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
{
WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__,
cacheSlot, gfx->MaxCacheSlot);
return ERROR_INVALID_INDEX;
}
gfx->CacheSlots[cacheSlot] = pData;
return CHANNEL_RC_OK;
@@ -1649,7 +1653,11 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
{
WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__,
cacheSlot, gfx->MaxCacheSlot);
return NULL;
}
pData = gfx->CacheSlots[cacheSlot];
return pData;
@@ -1716,11 +1724,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (gfx->H264)
gfx->SmallCache = TRUE;
if (gfx->SmallCache)
gfx->ThinClient = FALSE;
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
gfx->MaxCacheSlot = gfx->SmallCache ? 4096 : 25600;
context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext));
if (!context)
{

View File

@@ -2157,6 +2157,8 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "gfx-thin-client")
{
settings->GfxThinClient = arg->Value ? TRUE : FALSE;
if (settings->GfxThinClient)
settings->GfxSmallCache = TRUE;
settings->SupportGraphicsPipeline = TRUE;
}
CommandLineSwitchCase(arg, "gfx-small-cache")

View File

@@ -976,28 +976,27 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context,
const RECTANGLE_16* rect;
gdiGfxSurface* surface;
gdiGfxCacheEntry* cacheEntry;
rect = &(surfaceToCache->rectSrc);
surface = (gdiGfxSurface*) context->GetSurfaceData(context,
surfaceToCache->surfaceId);
rect = &(surfaceToCache->rectSrc);
surface = (gdiGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId);
if (!surface)
return ERROR_INTERNAL_ERROR;
cacheEntry = (gdiGfxCacheEntry*) calloc(1, sizeof(gdiGfxCacheEntry));
if (!cacheEntry)
return ERROR_INTERNAL_ERROR;
return ERROR_NOT_ENOUGH_MEMORY;
cacheEntry->width = (UINT32)(rect->right - rect->left);
cacheEntry->height = (UINT32)(rect->bottom - rect->top);
cacheEntry->format = surface->format;
cacheEntry->scanline = gfx_align_scanline(cacheEntry->width * 4, 16);
cacheEntry->data = (BYTE*) calloc(cacheEntry->height, cacheEntry->scanline);
cacheEntry->data = (BYTE*) calloc(cacheEntry->height, cacheEntry->scanline);
if (!cacheEntry->data)
{
free(cacheEntry);
return ERROR_INTERNAL_ERROR;
return ERROR_NOT_ENOUGH_MEMORY;
}
if (!freerdp_image_copy(cacheEntry->data, cacheEntry->format, cacheEntry->scanline,
@@ -1008,9 +1007,7 @@ static UINT gdi_SurfaceToCache(RdpgfxClientContext* context,
return ERROR_INTERNAL_ERROR;
}
context->SetCacheSlotData(context, surfaceToCache->cacheSlot,
(void*) cacheEntry);
return CHANNEL_RC_OK;
return context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry);
}
/**
@@ -1028,10 +1025,9 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context,
gdiGfxCacheEntry* cacheEntry;
RECTANGLE_16 invalidRect;
rdpGdi* gdi = (rdpGdi*) context->custom;
surface = (gdiGfxSurface*) context->GetSurfaceData(context,
cacheToSurface->surfaceId);
cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context,
cacheToSurface->cacheSlot);
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId);
cacheEntry = (gdiGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot);
if (!surface || !cacheEntry)
return ERROR_INTERNAL_ERROR;