mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user