Skip to content

Commit

Permalink
Replace some assertions by AVIF_ASSERT()
Browse files Browse the repository at this point in the history
  • Loading branch information
y-guyon committed Jan 19, 2024
1 parent 9f6e550 commit 2db8fa5
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 71 deletions.
11 changes: 11 additions & 0 deletions include/avif/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ static inline void avifBreakOnError()
} \
} while (0)

// Same as AVIF_CHECKERR() but also assert() in debug build configuration.
// Can be used instead of assert() for extra security.
#define AVIF_ASSERT(A, ERR) \
do { \
if (!(A)) { \
assert(AVIF_FALSE); \
avifBreakOnError(); \
return ERR; \
} \
} while (0)

// ---------------------------------------------------------------------------
// URNs and Content-Types

Expand Down
83 changes: 42 additions & 41 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ static avifResult avifCodecDecodeInputFillFromDecoderItem(avifCodecDecodeInput *
}
}
if (remainingSize > 0) {
assert(layerCount == 3);
AVIF_ASSERT(layerCount == 3, AVIF_RESULT_UNKNOWN_ERROR);
++layerCount;
layerSizes[3] = remainingSize;
}
Expand Down Expand Up @@ -611,7 +611,7 @@ static avifResult avifCodecDecodeInputFillFromDecoderItem(avifCodecDecodeInput *
sample->itemID = item->id;
sample->offset = 0;
sample->size = sampleSize;
assert(lselProp->u.lsel.layerID < AVIF_MAX_AV1_LAYER_COUNT);
AVIF_ASSERT(lselProp->u.lsel.layerID < AVIF_MAX_AV1_LAYER_COUNT, AVIF_RESULT_UNKNOWN_ERROR);
sample->spatialID = (uint8_t)lselProp->u.lsel.layerID;
sample->sync = AVIF_TRUE;
} else if (allowProgressive && item->progressive) {
Expand Down Expand Up @@ -790,7 +790,7 @@ static avifResult avifCheckItemID(const char * boxFourcc, uint32_t itemID, avifD
static avifResult avifMetaFindOrCreateItem(avifMeta * meta, uint32_t itemID, avifDecoderItem ** item)
{
*item = NULL;
assert(itemID != 0);
AVIF_ASSERT(itemID != 0, AVIF_RESULT_UNKNOWN_ERROR);

for (uint32_t i = 0; i < meta->items.count; ++i) {
if (meta->items.item[i]->id == itemID) {
Expand Down Expand Up @@ -1043,7 +1043,7 @@ static avifResult avifDecoderItemMaxExtent(const avifDecoderItem * item, const a
size_t remainingBytes = sample->size; // This may be smaller than item->size if the item is progressive

// Assert that the for loop below will execute at least one iteration.
assert(item->extents.count != 0);
AVIF_ASSERT(item->extents.count != 0, AVIF_RESULT_UNKNOWN_ERROR);
uint64_t minOffset = UINT64_MAX;
uint64_t maxOffset = 0;
for (uint32_t extentIter = 0; extentIter < item->extents.count; ++extentIter) {
Expand Down Expand Up @@ -1368,8 +1368,8 @@ static avifResult avifDecoderItemRead(avifDecoderItem * item,
memcpy(&item->mergedExtents, &offsetBuffer, sizeof(avifRWData));
item->mergedExtents.size = bytesToRead;
} else {
assert(item->ownsMergedExtents);
assert(front);
AVIF_ASSERT(item->ownsMergedExtents, AVIF_RESULT_UNKNOWN_ERROR);
AVIF_ASSERT(front, AVIF_RESULT_UNKNOWN_ERROR);
memcpy(front, offsetBuffer.data, bytesToRead);
front += bytesToRead;
}
Expand Down Expand Up @@ -1514,7 +1514,7 @@ static avifResult avifDecoderDataAllocateGridImagePlanes(avifDecoderData * data,
avifBool alpha = (tile->input->itemCategory == AVIF_ITEM_ALPHA);
if (alpha) {
// An alpha tile does not contain any YUV pixels.
assert(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE);
AVIF_ASSERT(tile->image->yuvFormat == AVIF_PIXEL_FORMAT_NONE, AVIF_RESULT_UNKNOWN_ERROR);
}
if (!avifAreGridDimensionsValid(tile->image->yuvFormat, grid->outputWidth, grid->outputHeight, tile->image->width, tile->image->height, data->diag)) {
return AVIF_RESULT_INVALID_IMAGE_GRID;
Expand Down Expand Up @@ -1600,15 +1600,13 @@ static avifBool avifDecoderDataCopyTileToImage(avifDecoderData * data,
avifImage * dst = dstImage;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
assert(dst->gainMap && dst->gainMap->image);
AVIF_ASSERT(dst->gainMap && dst->gainMap->image, AVIF_RESULT_UNKNOWN_ERROR);
dst = dst->gainMap->image;
}
#endif
if ((avifImageSetViewRect(&dstView, dst, &dstViewRect) != AVIF_RESULT_OK) ||
(avifImageSetViewRect(&srcView, tile->image, &srcViewRect) != AVIF_RESULT_OK)) {
assert(AVIF_FALSE);
return AVIF_FALSE;
}
AVIF_ASSERT(avifImageSetViewRect(&dstView, dst, &dstViewRect) == AVIF_RESULT_OK &&
avifImageSetViewRect(&srcView, tile->image, &srcViewRect) == AVIF_RESULT_OK,
AVIF_FALSE);
avifImageCopySamples(&dstView, &srcView, (tile->input->itemCategory == AVIF_ITEM_ALPHA) ? AVIF_PLANES_A : AVIF_PLANES_YUV);

return AVIF_TRUE;
Expand Down Expand Up @@ -1915,7 +1913,7 @@ static avifBool avifParseToneMappedImageBox(avifGainMapMetadata * metadata, cons
uint8_t flags;
AVIF_CHECK(avifROStreamRead(&s, &flags, 1)); // unsigned int(8) flags;
uint8_t channelCount = (flags & 1) * 2 + 1;
assert(channelCount == 1 || channelCount == 3);
AVIF_ASSERT(channelCount == 1 || channelCount == 3, AVIF_RESULT_UNKNOWN_ERROR);
metadata->useBaseColorSpace = (flags & 2) != 0;
metadata->backwardDirection = (flags & 4) != 0;
const avifBool useCommonDenominator = (flags & 8) != 0;
Expand Down Expand Up @@ -2013,13 +2011,13 @@ static avifResult avifDecoderItemReadAndParse(const avifDecoder * decoder,
} else {
// item was generated for convenience and is not part of the bitstream.
// grid information should already be set.
assert(grid->rows > 0 && grid->columns > 0);
AVIF_ASSERT(grid->rows > 0 && grid->columns > 0, AVIF_RESULT_UNKNOWN_ERROR);
}
*codecType = avifDecoderItemGetGridCodecType(item);
AVIF_CHECKERR(*codecType != AVIF_CODEC_TYPE_UNKNOWN, AVIF_RESULT_INVALID_IMAGE_GRID);
} else {
*codecType = avifGetCodecType(item->type);
assert(*codecType != AVIF_CODEC_TYPE_UNKNOWN);
AVIF_ASSERT(*codecType != AVIF_CODEC_TYPE_UNKNOWN, AVIF_RESULT_UNKNOWN_ERROR);
}
return AVIF_RESULT_OK;
}
Expand Down Expand Up @@ -2344,7 +2342,7 @@ static avifResult avifParseItemPropertyAssociation(avifMeta * meta, const uint8_
if (meta->fromConi) {
// The CondensedImageBox will always create 8 item properties, so to refer to the
// first property in the ItemPropertyContainerBox of its extendedMeta field, use index 9.
assert(meta->properties.count >= 8);
AVIF_ASSERT(meta->properties.count >= 8, AVIF_RESULT_UNKNOWN_ERROR);
}
#endif // AVIF_ENABLE_EXPERIMENTAL_AVIR

Expand Down Expand Up @@ -2631,7 +2629,7 @@ static avifResult avifParseItemInfoEntry(avifMeta * meta, const uint8_t * raw, s
AVIF_CHECKERR(avifROStreamReadU16(&s, &tmp), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(16) item_ID;
itemID = tmp;
} else {
assert(version == 3);
AVIF_ASSERT(version == 3, AVIF_RESULT_UNKNOWN_ERROR);
AVIF_CHECKERR(avifROStreamReadU32(&s, &itemID), AVIF_RESULT_BMFF_PARSE_FAILED); // unsigned int(32) item_ID;
}
AVIF_CHECKRES(avifCheckItemID("infe", itemID, diag));
Expand Down Expand Up @@ -3302,7 +3300,7 @@ static avifResult avifParseTrackBox(avifDecoderData * data,
//
// Since libavif uses repetitionCount (which is 0-based), we subtract the value by 1 to derive the number of
// repetitions.
assert(track->segmentDuration != 0);
AVIF_ASSERT(track->segmentDuration != 0, AVIF_RESULT_UNKNOWN_ERROR);
// We specifically check for trackDuration == 0 here and not when it is actually read in order to accept files which
// inadvertently has a trackDuration of 0 without any edit lists.
if (track->trackDuration == 0) {
Expand Down Expand Up @@ -3712,7 +3710,7 @@ static avifResult avifParseCondensedImageBox(avifMeta * meta, uint64_t rawOffset
// The ExtendedMetaBox may reuse items and properties created above so it must be parsed last.

if (hasExtendedMeta) {
assert(avifROStreamHasBytesLeft(&s, extendedMetaSize));
AVIF_ASSERT(avifROStreamHasBytesLeft(&s, extendedMetaSize), AVIF_RESULT_UNKNOWN_ERROR);
AVIF_CHECKRES(avifParseExtendedMeta(meta, rawOffset + avifROStreamOffset(&s), avifROStreamCurrent(&s), extendedMetaSize, diag));
}
return AVIF_RESULT_OK;
Expand Down Expand Up @@ -3780,7 +3778,7 @@ static avifResult avifParse(avifDecoder * decoder)
avifBoxHeader header;
AVIF_CHECKERR(avifROStreamReadBoxHeaderPartial(&headerStream, &header), AVIF_RESULT_BMFF_PARSE_FAILED);
parseOffset += headerStream.offset;
assert((decoder->io->sizeHint == 0) || (parseOffset <= decoder->io->sizeHint));
AVIF_ASSERT(decoder->io->sizeHint == 0 || parseOffset <= decoder->io->sizeHint, AVIF_RESULT_UNKNOWN_ERROR);

// Try to get the remainder of the box, if necessary
uint64_t boxOffset = 0;
Expand Down Expand Up @@ -4400,7 +4398,7 @@ static avifResult avifMetaFindAlphaItem(avifMeta * meta,
}
}
}
assert(alphaItemCount == colorItemCount);
AVIF_ASSERT(alphaItemCount == colorItemCount, AVIF_RESULT_UNKNOWN_ERROR);
// Find an unused ID.
avifResult result;
if (meta->items.count >= UINT32_MAX - 1) {
Expand Down Expand Up @@ -4512,7 +4510,7 @@ static avifResult avifDecoderDataFindToneMappedImageItem(const avifDecoderData *
continue;
}
if (otherItem->dimgIdx < 2) {
assert(dimgItemIDs[otherItem->dimgIdx] == 0);
AVIF_ASSERT(dimgItemIDs[otherItem->dimgIdx] == 0, AVIF_RESULT_UNKNOWN_ERROR);
dimgItemIDs[otherItem->dimgIdx] = otherItem->id;
}
numDimgItemIDs++;
Expand Down Expand Up @@ -4561,7 +4559,7 @@ static avifResult avifDecoderFindGainMapItem(const avifDecoder * decoder,
return AVIF_RESULT_OK;
}

assert(gainMapItemID != 0);
AVIF_ASSERT(gainMapItemID != 0, AVIF_RESULT_UNKNOWN_ERROR);
avifDecoderItem * gainMapItemTmp;
AVIF_CHECKRES(avifMetaFindOrCreateItem(data->meta, gainMapItemID, &gainMapItemTmp));
if (avifDecoderItemShouldBeSkipped(gainMapItemTmp)) {
Expand Down Expand Up @@ -4643,7 +4641,7 @@ static avifResult avifDecoderGenerateImageTiles(avifDecoder * decoder, avifTileI
AVIF_CHECKERR(item->size != 0, AVIF_RESULT_MISSING_IMAGE_ITEM);

const avifCodecType codecType = avifGetCodecType(item->type);
assert(codecType != AVIF_CODEC_TYPE_UNKNOWN);
AVIF_ASSERT(codecType != AVIF_CODEC_TYPE_UNKNOWN, AVIF_RESULT_UNKNOWN_ERROR);
avifTile * tile =
avifDecoderDataCreateTile(decoder->data, codecType, item->width, item->height, avifDecoderItemOperatingPoint(item));
AVIF_CHECKERR(tile, AVIF_RESULT_OUT_OF_MEMORY);
Expand Down Expand Up @@ -4960,7 +4958,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)
#endif
if (c == AVIF_ITEM_ALPHA && !mainItems[c]->width && !mainItems[c]->height) {
// NON-STANDARD: Alpha subimage does not have an ispe property; adopt width/height from color item
assert(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED));
AVIF_ASSERT(!(decoder->strictFlags & AVIF_STRICT_ALPHA_ISPE_REQUIRED), AVIF_RESULT_UNKNOWN_ERROR);
mainItems[c]->width = mainItems[AVIF_ITEM_COLOR]->width;
mainItems[c]->height = mainItems[AVIF_ITEM_COLOR]->height;
}
Expand Down Expand Up @@ -4995,7 +4993,7 @@ avifResult avifDecoderReset(avifDecoder * decoder)

#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (mainItems[AVIF_ITEM_GAIN_MAP]) {
assert(decoder->image->gainMap && decoder->image->gainMap->image);
AVIF_ASSERT(decoder->image->gainMap && decoder->image->gainMap->image, AVIF_RESULT_UNKNOWN_ERROR);
decoder->image->gainMap->image->width = mainItems[AVIF_ITEM_GAIN_MAP]->width;
decoder->image->gainMap->image->height = mainItems[AVIF_ITEM_GAIN_MAP]->height;
decoder->gainMapPresent = AVIF_TRUE;
Expand Down Expand Up @@ -5185,7 +5183,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma

const avifDecodeSample * sample = &tile->input->samples.sample[nextImageIndex];
if (sample->data.size < sample->size) {
assert(decoder->allowIncremental);
AVIF_ASSERT(decoder->allowIncremental, AVIF_RESULT_UNKNOWN_ERROR);
// Data is missing but there is no error yet. Output available pixel rows.
return AVIF_RESULT_OK;
}
Expand Down Expand Up @@ -5246,7 +5244,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
avifImage * dstImage = decoder->image;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
assert(dstImage->gainMap && dstImage->gainMap->image);
AVIF_ASSERT(dstImage->gainMap && dstImage->gainMap->image, AVIF_RESULT_UNKNOWN_ERROR);
dstImage = dstImage->gainMap->image;
}
#endif
Expand All @@ -5257,14 +5255,14 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
}
} else {
// Non-grid path. Just steal the planes from the only "tile".
assert(info->tileCount == 1);
assert(tileIndex == 0);
AVIF_ASSERT(info->tileCount == 1, AVIF_RESULT_UNKNOWN_ERROR);
AVIF_ASSERT(tileIndex == 0, AVIF_RESULT_UNKNOWN_ERROR);
avifImage * src = tile->image;

switch (tile->input->itemCategory) {
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
case AVIF_ITEM_GAIN_MAP:
assert(decoder->image->gainMap && decoder->image->gainMap->image);
AVIF_ASSERT(decoder->image->gainMap && decoder->image->gainMap->image, AVIF_RESULT_UNKNOWN_ERROR);
decoder->image->gainMap->image->width = src->width;
decoder->image->gainMap->image->height = src->height;
decoder->image->gainMap->image->depth = src->depth;
Expand All @@ -5291,7 +5289,7 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma
avifImageStealPlanes(decoder->image, src, AVIF_PLANES_A);
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
} else if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) {
assert(decoder->image->gainMap && decoder->image->gainMap->image);
AVIF_ASSERT(decoder->image->gainMap && decoder->image->gainMap->image, AVIF_RESULT_UNKNOWN_ERROR);
avifImageStealPlanes(decoder->image->gainMap->image, src, AVIF_PLANES_YUV);
#endif
} else { // AVIF_ITEM_COLOR
Expand Down Expand Up @@ -5333,8 +5331,9 @@ avifResult avifDecoderNextImage(avifDecoder * decoder)
}
}

assert(decoder->data->tiles.count == (decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].firstTileIndex +
decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].tileCount));
AVIF_ASSERT(decoder->data->tiles.count == (decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].firstTileIndex +
decoder->data->tileInfos[AVIF_ITEM_CATEGORY_COUNT - 1].tileCount),
AVIF_RESULT_UNKNOWN_ERROR);

const uint32_t nextImageIndex = (uint32_t)(decoder->imageIndex + 1);

Expand Down Expand Up @@ -5363,22 +5362,23 @@ avifResult avifDecoderNextImage(avifDecoder * decoder)
}

if (!avifDecoderDataFrameFullyDecoded(decoder->data)) {
assert(decoder->allowIncremental);
AVIF_ASSERT(decoder->allowIncremental, AVIF_RESULT_UNKNOWN_ERROR);
// The image is not completely decoded. There should be no error unrelated to missing bytes,
// and at least some missing bytes.
avifResult firstNonOkResult = AVIF_RESULT_OK;
for (int c = 0; c < AVIF_ITEM_CATEGORY_COUNT; ++c) {
assert((prepareTileResult[c] == AVIF_RESULT_OK) || (prepareTileResult[c] == AVIF_RESULT_WAITING_ON_IO));
AVIF_ASSERT(prepareTileResult[c] == AVIF_RESULT_OK || prepareTileResult[c] == AVIF_RESULT_WAITING_ON_IO,
AVIF_RESULT_UNKNOWN_ERROR);
if (firstNonOkResult == AVIF_RESULT_OK) {
firstNonOkResult = prepareTileResult[c];
}
}
assert(firstNonOkResult != AVIF_RESULT_OK);
AVIF_ASSERT(firstNonOkResult != AVIF_RESULT_OK, AVIF_RESULT_UNKNOWN_ERROR);
// Return the "not enough bytes" status now instead of moving on to the next frame.
return AVIF_RESULT_WAITING_ON_IO;
}
for (int c = 0; c < AVIF_ITEM_CATEGORY_COUNT; ++c) {
assert(prepareTileResult[c] == AVIF_RESULT_OK);
AVIF_ASSERT(prepareTileResult[c] == AVIF_RESULT_OK, AVIF_RESULT_UNKNOWN_ERROR);
}

// Only advance decoder->imageIndex once the image is completely decoded, so that
Expand Down Expand Up @@ -5555,8 +5555,9 @@ uint32_t avifDecoderDecodedRowCount(const avifDecoder * decoder)
const uint32_t scaledGainMapRowCount =
(uint32_t)floorf((float)gainMapRowCount / gainMap->height * decoder->image->height);
// Make sure it matches the formula described in the comment of avifDecoderDecodedRowCount() in avif.h.
assert((uint32_t)lround((double)scaledGainMapRowCount / decoder->image->height *
decoder->image->gainMap->image->height) <= gainMapRowCount);
AVIF_ASSERT((uint32_t)lround((double)scaledGainMapRowCount / decoder->image->height *
decoder->image->gainMap->image->height) <= gainMapRowCount,
0);
gainMapRowCount = scaledGainMapRowCount;
}
minRowCount = AVIF_MIN(minRowCount, gainMapRowCount);
Expand Down
Loading

0 comments on commit 2db8fa5

Please sign in to comment.