From 4e24b966c86fdf494a782f0dfcfc43a057a2ea60 Mon Sep 17 00:00:00 2001 From: David Fort Date: Tue, 9 May 2023 23:33:52 +0200 Subject: [PATCH] [codec,progressive] fix segfault and optimize updated tiles The number of updated tiles was not reset at the end of a progressive block treatment leading to possibly overflow the updatedTiles array. This patch also introduces a dirty bit on tiles, so that a tile updated multiple times is just mark once as modified. --- libfreerdp/codec/progressive.c | 52 ++++++++++++++++++++-------------- libfreerdp/codec/progressive.h | 1 + 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 49be2824c..813fbe64a 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -418,23 +418,24 @@ static INLINE RFX_PROGRESSIVE_TILE* progressive_tile_new(void) tile->height = 64; tile->stride = 4 * tile->width; - size_t dataLen = tile->stride * tile->height * 1ULL; - tile->data = (BYTE*)winpr_aligned_malloc(dataLen, 16); - if (!tile->data) - goto fail; - memset(tile->data, 0xFF, dataLen); + size_t dataLen = tile->stride * tile->height * 1ULL; + tile->data = (BYTE*)winpr_aligned_malloc(dataLen, 16); + if (!tile->data) + goto fail; + memset(tile->data, 0xFF, dataLen); - size_t signLen = (8192 + 32) * 3; - tile->sign = (BYTE*)winpr_aligned_calloc(signLen, sizeof(BYTE), 16); - if (!tile->sign) - goto fail; + size_t signLen = (8192 + 32) * 3; + tile->sign = (BYTE*)winpr_aligned_calloc(signLen, sizeof(BYTE), 16); + if (!tile->sign) + goto fail; - size_t currentLen = (8192 + 32) * 3; - tile->current = (BYTE*)winpr_aligned_calloc(currentLen, sizeof(BYTE), 16); - if (!tile->current) - goto fail; + size_t currentLen = (8192 + 32) * 3; + tile->current = (BYTE*)winpr_aligned_calloc(currentLen, sizeof(BYTE), 16); + if (!tile->current) + goto fail; + + return tile; - return tile; fail: progressive_tile_free(tile); return NULL; @@ -466,7 +467,7 @@ static BOOL progressive_allocate_tile_cache(PROGRESSIVE_SURFACE_CONTEXT* surface { surface->tiles[x] = progressive_tile_new(); if (!surface->tiles[x]) - return FALSE; + return FALSE; } tmp = @@ -569,14 +570,20 @@ static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surfac region->numTiles, region->usedTiles); return FALSE; } - if (surface->numUpdatedTiles >= surface->tilesSize) - { - if (!progressive_allocate_tile_cache(surface, surface->numUpdatedTiles)) - return FALSE; - } region->tiles[region->usedTiles++] = t; - surface->updatedTileIndices[surface->numUpdatedTiles++] = (UINT32)zIdx; + if (!t->dirty) + { + if (surface->numUpdatedTiles >= surface->gridSize) + { + if (!progressive_allocate_tile_cache(surface, surface->numUpdatedTiles + 1)) + return FALSE; + } + + surface->updatedTileIndices[surface->numUpdatedTiles++] = (UINT32)zIdx; + } + + t->dirty = TRUE; return TRUE; } @@ -2609,10 +2616,11 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD } region16_uninit(&updateRegion); + tile->dirty = FALSE; } region16_uninit(&clippingRects); - + surface->numUpdatedTiles = 0; fail: return rc; } diff --git a/libfreerdp/codec/progressive.h b/libfreerdp/codec/progressive.h index d3de10c18..860807fea 100644 --- a/libfreerdp/codec/progressive.h +++ b/libfreerdp/codec/progressive.h @@ -101,6 +101,7 @@ typedef struct BYTE flags; BYTE quality; + BOOL dirty; UINT16 yLen; UINT16 cbLen;