Validate CICP in all code paths Color Primaries, Transfer Characteristics and Matrix Coefficients are read from the bitstream in multiple places. Make sure they are validated in all the paths.
diff --git a/src/read.c b/src/read.c index ed56d28..c06a4d3 100644 --- a/src/read.c +++ b/src/read.c
@@ -1519,6 +1519,22 @@ return AVIF_RESULT_OK; } +static void clampCicpToValidRange(avifColorPrimaries * colorPrimaries, + avifTransferCharacteristics * transferCharacteristics, + avifMatrixCoefficients * matrixCoefficients) +{ + if (*colorPrimaries == 3 || (*colorPrimaries > AVIF_COLOR_PRIMARIES_DCI_P3 && *colorPrimaries < AVIF_COLOR_PRIMARIES_EBU3213) || + *colorPrimaries > AVIF_COLOR_PRIMARIES_EBU3213) { + *colorPrimaries = AVIF_COLOR_PRIMARIES_UNSPECIFIED; + } + if (*transferCharacteristics == 3 || *transferCharacteristics > AVIF_TRANSFER_CHARACTERISTICS_HLG) { + *transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED; + } + if (*matrixCoefficients == 3 || *matrixCoefficients >= AVIF_MATRIX_COEFFICIENTS_LAST) { + *matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED; + } +} + // Allocates the dstImage. Also verifies some spec compliance rules for grids, if relevant. static avifResult avifDecoderDataAllocateImagePlanes(avifDecoderData * data, const avifTileInfo * info, avifImage * dstImage) { @@ -1597,6 +1613,7 @@ dstImage->colorPrimaries = tile->image->colorPrimaries; dstImage->transferCharacteristics = tile->image->transferCharacteristics; dstImage->matrixCoefficients = tile->image->matrixCoefficients; + clampCicpToValidRange(&dstImage->colorPrimaries, &dstImage->transferCharacteristics, &dstImage->matrixCoefficients); } } @@ -2222,20 +2239,10 @@ colr->iccOffset = rawOffset + avifROStreamOffset(&s); colr->iccSize = avifROStreamRemainingBytes(&s); } else if (!memcmp(colorType, "nclx", 4)) { - AVIF_CHECK(avifROStreamReadU16(&s, &colr->colorPrimaries)); // unsigned int(16) colour_primaries; - if (colr->colorPrimaries == 3 || - (colr->colorPrimaries > AVIF_COLOR_PRIMARIES_DCI_P3 && colr->colorPrimaries < AVIF_COLOR_PRIMARIES_EBU3213) || - colr->colorPrimaries > AVIF_COLOR_PRIMARIES_EBU3213) { - colr->colorPrimaries = AVIF_COLOR_PRIMARIES_UNSPECIFIED; - } + AVIF_CHECK(avifROStreamReadU16(&s, &colr->colorPrimaries)); // unsigned int(16) colour_primaries; AVIF_CHECK(avifROStreamReadU16(&s, &colr->transferCharacteristics)); // unsigned int(16) transfer_characteristics; - if (colr->transferCharacteristics == 3 || colr->transferCharacteristics > AVIF_TRANSFER_CHARACTERISTICS_HLG) { - colr->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_UNSPECIFIED; - } - AVIF_CHECK(avifROStreamReadU16(&s, &colr->matrixCoefficients)); // unsigned int(16) matrix_coefficients; - if (colr->matrixCoefficients == 3 || colr->matrixCoefficients >= AVIF_MATRIX_COEFFICIENTS_LAST) { - colr->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED; - } + AVIF_CHECK(avifROStreamReadU16(&s, &colr->matrixCoefficients)); // unsigned int(16) matrix_coefficients; + clampCicpToValidRange(&colr->colorPrimaries, &colr->transferCharacteristics, &colr->matrixCoefficients); uint8_t full_range_flag; AVIF_CHECK(avifROStreamReadBits8(&s, &full_range_flag, /*bitCount=*/1)); // unsigned int(1) full_range_flag; colr->range = full_range_flag ? AVIF_RANGE_FULL : AVIF_RANGE_LIMITED; @@ -4695,6 +4702,7 @@ *colorPrimaries = prop->u.colr.colorPrimaries; *transferCharacteristics = prop->u.colr.transferCharacteristics; *matrixCoefficients = prop->u.colr.matrixCoefficients; + clampCicpToValidRange(colorPrimaries, transferCharacteristics, matrixCoefficients); *yuvRange = prop->u.colr.range; } } @@ -4835,6 +4843,9 @@ gainMap->image->colorPrimaries = prop->u.colr.colorPrimaries; gainMap->image->transferCharacteristics = prop->u.colr.transferCharacteristics; gainMap->image->matrixCoefficients = prop->u.colr.matrixCoefficients; + clampCicpToValidRange(&gainMap->image->colorPrimaries, + &gainMap->image->transferCharacteristics, + &gainMap->image->matrixCoefficients); gainMap->image->yuvRange = prop->u.colr.range; break; } @@ -5422,6 +5433,9 @@ decoder->image->colorPrimaries = sequenceHeader.colorPrimaries; decoder->image->transferCharacteristics = sequenceHeader.transferCharacteristics; decoder->image->matrixCoefficients = sequenceHeader.matrixCoefficients; + clampCicpToValidRange(&decoder->image->colorPrimaries, + &decoder->image->transferCharacteristics, + &decoder->image->matrixCoefficients); decoder->image->yuvRange = sequenceHeader.range; break; }