Skip to content

Commit 2ff2b81

Browse files
committed
Convert avifDecoderItemArray into an array of pointers
Port commit 0679908 and commit 380fb99 to the v1.0.x branch. Instead of storing the struct directly in a dynamic array, store it as pointers that are stored in a dynamic array. This way when the dynamic array is resized, the pointers will still be valid and be copied over and there will be no dangling pointers.
1 parent 0142a0d commit 2ff2b81

1 file changed

Lines changed: 24 additions & 20 deletions

File tree

src/read.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ typedef struct avifDecoderItem
203203
avifBool ipmaSeen; // if true, this item already received a property association
204204
avifBool progressive; // if true, this item has progressive layers (a1lx), but does not select a specific layer (the layer_id value in lsel is set to 0xFFFF)
205205
} avifDecoderItem;
206-
AVIF_ARRAY_DECLARE(avifDecoderItemArray, avifDecoderItem, item);
206+
AVIF_ARRAY_DECLARE(avifDecoderItemArray, avifDecoderItem *, item);
207207

208208
// grid storage
209209
typedef struct avifImageGrid
@@ -740,7 +740,7 @@ static avifMeta * avifMetaCreate()
740740
{
741741
avifMeta * meta = (avifMeta *)avifAlloc(sizeof(avifMeta));
742742
memset(meta, 0, sizeof(avifMeta));
743-
if (!avifArrayCreate(&meta->items, sizeof(avifDecoderItem), 8)) {
743+
if (!avifArrayCreate(&meta->items, sizeof(avifDecoderItem *), 8)) {
744744
goto error;
745745
}
746746
if (!avifArrayCreate(&meta->properties, sizeof(avifProperty), 16)) {
@@ -756,12 +756,13 @@ static avifMeta * avifMetaCreate()
756756
static void avifMetaDestroy(avifMeta * meta)
757757
{
758758
for (uint32_t i = 0; i < meta->items.count; ++i) {
759-
avifDecoderItem * item = &meta->items.item[i];
759+
avifDecoderItem * item = meta->items.item[i];
760760
avifArrayDestroy(&item->properties);
761761
avifArrayDestroy(&item->extents);
762762
if (item->ownsMergedExtents) {
763763
avifRWDataFree(&item->mergedExtents);
764764
}
765+
avifFree(item);
765766
}
766767
avifArrayDestroy(&meta->items);
767768
avifArrayDestroy(&meta->properties);
@@ -778,12 +779,13 @@ static avifDecoderItem * avifMetaFindItem(avifMeta * meta, uint32_t itemID)
778779
}
779780

780781
for (uint32_t i = 0; i < meta->items.count; ++i) {
781-
if (meta->items.item[i].id == itemID) {
782-
return &meta->items.item[i];
782+
if (meta->items.item[i]->id == itemID) {
783+
return meta->items.item[i];
783784
}
784785
}
785786

786-
avifDecoderItem * item = (avifDecoderItem *)avifArrayPushPtr(&meta->items);
787+
avifDecoderItem * item = (avifDecoderItem *)avifAlloc(sizeof(avifDecoderItem));
788+
memset(item, 0, sizeof(avifDecoderItem));
787789
if (!avifArrayCreate(&item->properties, sizeof(avifProperty), 16)) {
788790
goto error;
789791
}
@@ -792,12 +794,14 @@ static avifDecoderItem * avifMetaFindItem(avifMeta * meta, uint32_t itemID)
792794
}
793795
item->id = itemID;
794796
item->meta = meta;
797+
avifDecoderItem ** itemPtr = (avifDecoderItem **)avifArrayPushPtr(&meta->items);
798+
*itemPtr = item;
795799
return item;
796800

797801
error:
798802
avifArrayDestroy(&item->extents);
799803
avifArrayDestroy(&item->properties);
800-
avifArrayPop(&meta->items);
804+
avifFree(item);
801805
return NULL;
802806
}
803807

@@ -1090,7 +1094,7 @@ static avifResult avifDecoderItemValidateProperties(const avifDecoderItem * item
10901094

10911095
if (!memcmp(item->type, "grid", 4)) {
10921096
for (uint32_t i = 0; i < item->meta->items.count; ++i) {
1093-
avifDecoderItem * tile = &item->meta->items.item[i];
1097+
avifDecoderItem * tile = item->meta->items.item[i];
10941098
if (tile->dimgForID != item->id) {
10951099
continue;
10961100
}
@@ -1330,7 +1334,7 @@ static avifResult avifDecoderItemRead(avifDecoderItem * item,
13301334
static avifCodecType avifDecoderItemGetGridCodecType(const avifDecoderItem * gridItem)
13311335
{
13321336
for (uint32_t i = 0; i < gridItem->meta->items.count; ++i) {
1333-
avifDecoderItem * item = &gridItem->meta->items.item[i];
1337+
avifDecoderItem * item = gridItem->meta->items.item[i];
13341338
const avifCodecType tileCodecType = avifGetCodecType(item->type);
13351339
if ((item->dimgForID == gridItem->id) && (tileCodecType != AVIF_CODEC_TYPE_UNKNOWN)) {
13361340
return tileCodecType;
@@ -1345,7 +1349,7 @@ static avifBool avifDecoderGenerateImageGridTiles(avifDecoder * decoder, avifIma
13451349
unsigned int tilesAvailable = 0;
13461350
avifDecoderItem * firstTileItem = NULL;
13471351
for (uint32_t i = 0; i < gridItem->meta->items.count; ++i) {
1348-
avifDecoderItem * item = &gridItem->meta->items.item[i];
1352+
avifDecoderItem * item = gridItem->meta->items.item[i];
13491353
if (item->dimgForID != gridItem->id) {
13501354
continue;
13511355
}
@@ -1550,7 +1554,7 @@ static avifResult avifDecoderFindMetadata(avifDecoder * decoder, avifMeta * meta
15501554
}
15511555

15521556
for (uint32_t itemIndex = 0; itemIndex < meta->items.count; ++itemIndex) {
1553-
avifDecoderItem * item = &meta->items.item[itemIndex];
1557+
avifDecoderItem * item = meta->items.item[itemIndex];
15541558
if (!item->size) {
15551559
continue;
15561560
}
@@ -3455,7 +3459,7 @@ avifResult avifDecoderParse(avifDecoder * decoder)
34553459
// Walk the decoded items (if any) and harvest ispe
34563460
avifDecoderData * data = decoder->data;
34573461
for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) {
3458-
avifDecoderItem * item = &data->meta->items.item[itemIndex];
3462+
avifDecoderItem * item = data->meta->items.item[itemIndex];
34593463
if (!item->size) {
34603464
continue;
34613465
}
@@ -3595,7 +3599,7 @@ static avifBool avifDecoderItemShouldBeSkipped(const avifDecoderItem * item)
35953599
static avifDecoderItem * avifDecoderDataFindColorItem(avifDecoderData * data)
35963600
{
35973601
for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) {
3598-
avifDecoderItem * item = &data->meta->items.item[itemIndex];
3602+
avifDecoderItem * item = data->meta->items.item[itemIndex];
35993603
if (avifDecoderItemShouldBeSkipped(item)) {
36003604
continue;
36013605
}
@@ -3631,7 +3635,7 @@ static avifResult avifDecoderDataFindAlphaItem(avifDecoderData * data,
36313635
{
36323636
const avifDecoderItem * colorItem = *colorItemPtr;
36333637
for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) {
3634-
avifDecoderItem * item = &data->meta->items.item[itemIndex];
3638+
avifDecoderItem * item = data->meta->items.item[itemIndex];
36353639
if (avifDecoderItemShouldBeSkipped(item)) {
36363640
continue;
36373641
}
@@ -3659,14 +3663,14 @@ static avifResult avifDecoderDataFindAlphaItem(avifDecoderData * data,
36593663
uint32_t alphaItemCount = 0;
36603664
uint32_t maxItemID = 0;
36613665
for (uint32_t i = 0; i < colorItem->meta->items.count; ++i) {
3662-
avifDecoderItem * item = &colorItem->meta->items.item[i];
3666+
avifDecoderItem * item = colorItem->meta->items.item[i];
36633667
if (item->id > maxItemID) {
36643668
maxItemID = item->id;
36653669
}
36663670
if (item->dimgForID == colorItem->id) {
36673671
avifBool seenAlphaForCurrentItem = AVIF_FALSE;
36683672
for (uint32_t j = 0; j < colorItem->meta->items.count; ++j) {
3669-
avifDecoderItem * auxlItem = &colorItem->meta->items.item[j];
3673+
avifDecoderItem * auxlItem = colorItem->meta->items.item[j];
36703674
if (avifDecoderItemIsAlphaAux(auxlItem, item->id)) {
36713675
if (seenAlphaForCurrentItem || auxlItem->dimgForID != 0) {
36723676
// One of the following invalid cases:
@@ -3694,7 +3698,7 @@ static avifResult avifDecoderDataFindAlphaItem(avifDecoderData * data,
36943698

36953699
int colorItemIndex = -1;
36963700
for (uint32_t i = 0; i < data->meta->items.count; ++i) {
3697-
if (colorItem->id == data->meta->items.item[i].id) {
3701+
if (colorItem->id == data->meta->items.item[i]->id) {
36983702
colorItemIndex = i;
36993703
break;
37003704
}
@@ -3708,14 +3712,14 @@ static avifResult avifDecoderDataFindAlphaItem(avifDecoderData * data,
37083712
return AVIF_RESULT_OUT_OF_MEMORY;
37093713
}
37103714
// avifMetaFindItem() could invalidate all existing item pointers. So reset the colorItem pointers.
3711-
*colorItemPtr = &data->meta->items.item[colorItemIndex];
3715+
*colorItemPtr = data->meta->items.item[colorItemIndex];
37123716
colorItem = *colorItemPtr;
37133717

37143718
memcpy((*alphaItem)->type, "grid", 4);
37153719
(*alphaItem)->width = colorItem->width;
37163720
(*alphaItem)->height = colorItem->height;
37173721
for (uint32_t i = 0; i < alphaItemCount; ++i) {
3718-
avifDecoderItem * item = &colorItem->meta->items.item[alphaItemIndices[i]];
3722+
avifDecoderItem * item = colorItem->meta->items.item[alphaItemIndices[i]];
37193723
item->dimgForID = (*alphaItem)->id;
37203724
}
37213725
avifFree(alphaItemIndices);
@@ -3951,7 +3955,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)
39513955
// Validate that there are exactly the same number of dimg items to form the grid.
39523956
uint32_t dimgItemCount = 0;
39533957
for (uint32_t i = 0; i < colorItem->meta->items.count; ++i) {
3954-
if (colorItem->meta->items.item[i].dimgForID == colorItem->id) {
3958+
if (colorItem->meta->items.item[i]->dimgForID == colorItem->id) {
39553959
++dimgItemCount;
39563960
}
39573961
}

0 commit comments

Comments
 (0)