[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.
This commit is contained in:
David Fort 2023-05-09 23:33:52 +02:00 committed by akallabeth
parent 6ec762fdec
commit 4e24b966c8
2 changed files with 31 additions and 22 deletions

View File

@ -418,23 +418,24 @@ static INLINE RFX_PROGRESSIVE_TILE* progressive_tile_new(void)
tile->height = 64; tile->height = 64;
tile->stride = 4 * tile->width; tile->stride = 4 * tile->width;
size_t dataLen = tile->stride * tile->height * 1ULL; size_t dataLen = tile->stride * tile->height * 1ULL;
tile->data = (BYTE*)winpr_aligned_malloc(dataLen, 16); tile->data = (BYTE*)winpr_aligned_malloc(dataLen, 16);
if (!tile->data) if (!tile->data)
goto fail; goto fail;
memset(tile->data, 0xFF, dataLen); memset(tile->data, 0xFF, dataLen);
size_t signLen = (8192 + 32) * 3; size_t signLen = (8192 + 32) * 3;
tile->sign = (BYTE*)winpr_aligned_calloc(signLen, sizeof(BYTE), 16); tile->sign = (BYTE*)winpr_aligned_calloc(signLen, sizeof(BYTE), 16);
if (!tile->sign) if (!tile->sign)
goto fail; goto fail;
size_t currentLen = (8192 + 32) * 3; size_t currentLen = (8192 + 32) * 3;
tile->current = (BYTE*)winpr_aligned_calloc(currentLen, sizeof(BYTE), 16); tile->current = (BYTE*)winpr_aligned_calloc(currentLen, sizeof(BYTE), 16);
if (!tile->current) if (!tile->current)
goto fail; goto fail;
return tile;
return tile;
fail: fail:
progressive_tile_free(tile); progressive_tile_free(tile);
return NULL; return NULL;
@ -466,7 +467,7 @@ static BOOL progressive_allocate_tile_cache(PROGRESSIVE_SURFACE_CONTEXT* surface
{ {
surface->tiles[x] = progressive_tile_new(); surface->tiles[x] = progressive_tile_new();
if (!surface->tiles[x]) if (!surface->tiles[x])
return FALSE; return FALSE;
} }
tmp = tmp =
@ -569,14 +570,20 @@ static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surfac
region->numTiles, region->usedTiles); region->numTiles, region->usedTiles);
return FALSE; return FALSE;
} }
if (surface->numUpdatedTiles >= surface->tilesSize)
{
if (!progressive_allocate_tile_cache(surface, surface->numUpdatedTiles))
return FALSE;
}
region->tiles[region->usedTiles++] = t; 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; return TRUE;
} }
@ -2609,10 +2616,11 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD
} }
region16_uninit(&updateRegion); region16_uninit(&updateRegion);
tile->dirty = FALSE;
} }
region16_uninit(&clippingRects); region16_uninit(&clippingRects);
surface->numUpdatedTiles = 0;
fail: fail:
return rc; return rc;
} }

View File

@ -101,6 +101,7 @@ typedef struct
BYTE flags; BYTE flags;
BYTE quality; BYTE quality;
BOOL dirty;
UINT16 yLen; UINT16 yLen;
UINT16 cbLen; UINT16 cbLen;